# -*- coding: utf-8 -*-
"""
Created on Thu Jul 13 14:25:02 2023

@author: Matteo Meli
"""

#                              
# ANALYSIS ON TIDE GAUGES -----------------------------------------------------
# -----------------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------


import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
sns.set_style("ticks")
sns.set_context("paper")
plt.yticks(fontname = "Times New Roman")
plt.xticks(fontname = "Times New Roman")
plt.rcParams["font.family"] = "Times New Roman"
import matplotlib.dates as mdates
from datetime import datetime
from netCDF4 import Dataset
import matplotlib.colors as colors
from datetime import timedelta
from PyEMD import EEMD
eemd = EEMD()
from scipy.signal import argrelextrema


datesat = pd.date_range('1/1/1993','12/31/2021', freq='Y')
datesat2 = pd.date_range('1/1/1993','12/31/2022', freq='Y')
datesat_m = pd.date_range('1/1/1993','12/31/2021', freq='M')

def read_basin_data(file_path, date_index, column_names=None):
    if column_names is None:
        column_names = ['mean','std']
    basin_data = pd.read_csv(file_path, delim_whitespace=True, header=None, names=column_names)
    basin_data.index = date_index
    basin_data.index = basin_data.index - pd.DateOffset(months=11)
    return basin_data
file_base_path = 'path/'
adria = read_basin_data(file_base_path + 'adriatic_basin_2.txt', datesat2)
ion_basin = read_basin_data(file_base_path + 'ionian_basin_2.txt', datesat2)
levantine = read_basin_data(file_base_path + 'levantine_basin_2.txt', datesat2)
egeo = read_basin_data(file_base_path + 'aegean_basin_2.txt', datesat2)
tyr_basin = read_basin_data(file_base_path + 'tyrrhenian_sea_basin_2.txt', datesat2)
west_basin = read_basin_data(file_base_path + 'western_mediterranean_basin_2.txt', datesat2)
scm_basin = read_basin_data(file_base_path + 'south_central_mediterranean_basin_2.txt', datesat2)
#------
adria_basin = adria['mean']
lev_basin = levantine['mean']
egeo_basin = egeo['mean']
western_med = (west_basin['mean'] + tyr_basin['mean']) / 2
ion_basin_combined = (ion_basin['mean'] + scm_basin['mean']) / 2
med = (western_med + ion_basin_combined + adria_basin + lev_basin + egeo_basin) / 5
adria_basin_std = adria['std']
lev_basin_std = levantine['std']
egeo_basin_std = egeo['std']
western_med_std = (west_basin['std'] + tyr_basin['std']) / 2
ion_basin_combined_std = (ion_basin['std'] + scm_basin['std']) / 2
med_std = (western_med_std + ion_basin_combined_std + adria_basin_std + lev_basin_std + egeo_basin_std) / 5

era20c = Dataset("path/ERA-20C_mslp.nc")
era20c.variables.keys()
pressure_era20c = era20c.variables['MSL_GDS4_SFC'][:,:,:]
dateera20c = pd.date_range(start='1900-01-01', end='2010-12-31 21:00', freq='3H')
lat_era20c = era20c.variables['g4_lat_1'][:]
lon_era20c = era20c.variables['g4_lon_2'][:]
lon_era20c_2 = np.where(lon_era20c > 180, lon_era20c - 360, lon_era20c)

era5 = Dataset("path/ERA5_mslp.nc")
era5.variables.keys()
lat_era5 = era5.variables['latitude'][:]
lon_era5 = era5.variables['longitude'][:]
pressure_era5 = era5.variables['msl'][:,:,:] 
dateera5 = pd.date_range('1/1/1940', '1/1/2023', freq='6H')
dateera5 = dateera5[:-1] 

alpha = -9.948  # in mm/hPa

barystatic = Dataset("path/total.nc")
barystatic.variables.keys()
lat_barystatic = barystatic.variables['lat'][:]
lon_barystatic = barystatic.variables['lon'][:]
sea_barystatic = barystatic.variables['total_rsl_mean'][:,:,:]# mm
barystatic.variables['time'] # 1900-2018
lon_barystatic2 = np.where(lon_barystatic > 180, lon_barystatic - 360, lon_barystatic)
lon_barystatic2.sort()
datebary = pd.date_range('1/1/1900','12/31/2018', freq='Y')


# NO GRD FILES MEANS NO CORRECTION FOR GRD EFFECT EMPLOYED
# num_ensembles is already *100 within the algorithm; thus, set it to 100 for a 10000 repetitions ensemble


# ADRIATIC SEA

# - - ---------- TRIESTE
trieste=pd.read_csv('path/trieste.txt',\
                 sep=';',header=None)[:]
datetri = pd.date_range('1/1/1875','12/31/2021', freq='M')
trieste.index = datetri
trieste.loc[trieste[3] == 10, 1] = np.nan
tri = trieste[1]
tri = tri.replace(-99999, np.nan)
valid_counts_per_year = tri.groupby(tri.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    tri[tri.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,2,19]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = tri - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,0,41]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = tri - (alpha * era5_anomaly)
tri = ib_0.combine_first(ib_1)
# --
tri_y = tri.resample('Y').mean()
tri_y = tri_y['1901-12-31':]
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
tri_y = interpolate_short_gaps(tri_y.copy())
# GIA
trend = -0.15
time_passed = np.arange(tri_y.shape[0])[:]
cumulative_trend = time_passed * trend
tri_y = tri_y - cumulative_trend
tri_y2 = tri_y.dropna()
# GRD
grd = sea_barystatic[:,271,387]
grd = pd.Series(grd, index=datebary)
tri_y = tri_y - grd
tri_y = tri_y.dropna()

sea = tri_y.values
num_ensembles = 1 
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean = imfs_sum / num_ensembles
imfs_mean[3] = imfs_mean[3] - np.mean(imfs_mean[3])
imfs_mean[4] = imfs_mean[4] - np.mean(imfs_mean[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Trieste", y=0.83)
for n, imf in enumerate(imfs_mean):
    plt.subplot(len(imfs_mean)+1, 1, n+2)
    plt.plot(tri_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_trieste.npy', imfs_mean)
#np.save('imfs_trieste_nogrd.npy', imfs_mean)
imfs_trieste = np.load('path/imfs_trieste.npy')
imfs_trieste_nogrd = np.load('path/imfs_trieste_nogrd.npy')

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Trieste", y=0.78)
num_plots = len(imfs_trieste)
for n in range(num_plots):
    plt.subplot(num_plots+1, 1, n+2)
    plt.plot(tri_y.index, imfs_trieste[n], 'red') # 'b' sta per "blue"
    plt.plot(tri_y2.index, imfs_trieste_nogrd[n], 'black')
    plt.ylabel("IMF %i" % (n+1))
    combined_imf = np.concatenate([imfs_trieste[n], imfs_trieste_nogrd[n]])
    plt.ylim(combined_imf.min(), combined_imf.max())
    plt.locator_params(axis='y', nbins=2)
    plt.axhline(y=0, color='black', linestyle='--', linewidth=0.5)
    if n+2 != num_plots+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == num_plots+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.subplot(num_plots+1, 1, 2)
plt.show()


# - - - - - - VENEZIA
# - - -------------------------------------------------------------------------
#------------------------------------------------------------------------------
venice = pd.read_csv('path/venice.txt',\
                 delim_whitespace=True,header=None)[:]
dateven = pd.date_range('1/1/1873','12/31/2019', freq='Y')
venice.index = dateven
ven_y = venice[0]
# no GIA correction needed, already corrected for total VLMs
# IB
era20c_hPa = pressure_era20c[:,2,18]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('Y').mean()
ib_0 = ven_y - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,1,39]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('Y').mean()
ib_1 = ven_y - (alpha * era5_anomaly)
ven_y = ib_0.combine_first(ib_1)
# - -
ven_y2 = ven_y.dropna()
# GRD
grd = sea_barystatic[:,270,384]
grd = pd.Series(grd, index=datebary)
ven_y = ven_y - grd
ven_y = ven_y.dropna()

sea = ven_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean2 = imfs_sum / num_ensembles
imfs_mean2[3] = imfs_mean2[3] - np.mean(imfs_mean2[3])
imfs_mean2[4] = imfs_mean2[4] - np.mean(imfs_mean2[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Venice", y=0.83)
for n, imf in enumerate(imfs_mean2):
    plt.subplot(len(imfs_mean2)+1, 1, n+2)
    plt.plot(ven_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean2)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean2)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_venice.npy', imfs_mean2)
#np.save('imfs_venice_nogrd.npy', imfs_mean2)
imfs_venice = np.load('path/imfs_venice.npy')
imfs_venice_nogrd = np.load('path/imfs_venice_nogrd.npy')


# -----------------------------------------------------------------------------
#   RAVENNA  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
# --------------------------------
rav=pd.read_csv('path/porto corsini.txt',\
                 delim_whitespace=True,header=None)[:]
daterav = pd.date_range('8/1/1873','12/31/2015', freq='M')
rav.index = daterav
rav = rav[1]
valid_counts_per_year = rav.groupby(rav.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    rav[rav.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,3,18]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = rav - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,3,39]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = rav - (alpha * era5_anomaly)
rav = ib_0.combine_first(ib_1)
# --
rav_y = rav.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    series_copy = series.copy()
    start_gap = None
    for i in range(len(series_copy)):
        if pd.isna(series_copy.iloc[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series_copy.iloc[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                if start_gap == 0:
                    series_copy.iloc[:end_gap] = series_copy.iloc[:end_gap + 1].interpolate().iloc[:-1]
                elif end_gap == len(series_copy):
                    series_copy.iloc[start_gap:] = series_copy.iloc[start_gap - 1:].interpolate().iloc[1:]
                else:
                    series_copy.iloc[start_gap:end_gap] = series_copy.iloc[start_gap - 1:end_gap + 1].interpolate().iloc[1:-1]
            start_gap = None
    return series_copy
rav_y = interpolate_short_gaps(rav_y)
# GIA
trend = -0.12
time_passed = np.arange(rav_y.shape[0])[:]
cumulative_trend = time_passed * trend
rav_y = rav_y - cumulative_trend
# GRD
grd = sea_barystatic[:,268,384]
grd = pd.Series(grd, index=datebary)
rav_y = rav_y - grd
rav_y_old = rav_y['1900':'1921']
rav_y = rav_y['1934':]
rav_y = rav_y.dropna()

sea = rav_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean3 = imfs_sum / num_ensembles
imfs_mean3[2] = imfs_mean3[2] - np.mean(imfs_mean3[2])
imfs_mean3[3] = imfs_mean3[3] - np.mean(imfs_mean3[3])
imfs_mean3[4] = imfs_mean3[4] - np.mean(imfs_mean3[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Porto Corsini", y=0.83)
for n, imf in enumerate(imfs_mean3):
    plt.subplot(len(imfs_mean3)+1, 1, n+2)
    plt.plot(rav_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean3)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean3)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_ravenna.npy', imfs_mean3)
#np.save('imfs_ravenna_nogrd.npy', imfs_mean3)
imfs_ravenna = np.load('path/imfs_ravenna.npy')
imfs_ravenna_nogrd = np.load('path/imfs_ravenna_nogrd.npy')

# - - - - - - - - - - - - - - - - - RAVENNA OLDER PART
#  - - - - - - - - - - - - - - - - - 

sea = rav_y_old.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean22 = imfs_sum / num_ensembles
imfs_mean22[2] = imfs_mean22[2] - np.mean(imfs_mean22[2])
imfs_mean22[1] = imfs_mean22[1] - np.mean(imfs_mean22[1])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Porto Corsini", y=0.83)
for n, imf in enumerate(imfs_mean22):
    plt.subplot(len(imfs_mean22)+1, 1, n+2)
    plt.plot(rav_y_old.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean22)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean22)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_ravenna_old.npy', imfs_mean22)
#np.save('imfs_ravenna_old_nogrd.npy', imfs_mean22)
imfs_ravenna_old = np.load('path/imfs_ravenna_old.npy')
imfs_ravenna_old_nogrd = np.load('path/imfs_ravenna_old_nogrd.npy')


#    ROVINJ -------------------------------------------------------------------
# -----------------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - -------------------------------------
rov=pd.read_csv('path/rovinj.txt',\
                 sep=';',header=None)[:]
daterov = pd.date_range('6/1/1955','12/31/2018', freq='M')
rov.index = daterov
rov = rov[1]
rov = rov.replace(-99999, np.nan)
valid_counts_per_year = rov.groupby(rov.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    rov[rov.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,2,19]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = rov - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,2,41]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = rov - (alpha * era5_anomaly)
rov = ib_0.combine_first(ib_1)
# - -
rov_y = rov.resample('Y').mean()
rov_y = rov_y['1956':] # no missing data
# GIA
trend = -0.12
time_passed = np.arange(rov_y.shape[0])[:]
cumulative_trend = time_passed * trend
rov_y = rov_y - cumulative_trend
# GRD
grd = sea_barystatic[:,270,387]
grd = pd.Series(grd, index=datebary)
rov_y = rov_y - grd
rov_y = rov_y.dropna()

sea = rov_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean4 = imfs_sum / num_ensembles
imfs_mean4[4] = imfs_mean4[4] - np.mean(imfs_mean4[4])
imfs_mean4[3] = imfs_mean4[3] - np.mean(imfs_mean4[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Rovinj", y=0.83)
for n, imf in enumerate(imfs_mean4):
    plt.subplot(len(imfs_mean4)+1, 1, n+2)
    plt.plot(rov_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean4)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean4)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_rovinj.npy', imfs_mean4)
#np.save('imfs_rovinj_nogrd.npy', imfs_mean4)
imfs_rovinj = np.load('path/imfs_rovinj.npy')
imfs_rovinj_nogrd = np.load('path/imfs_rovinj_nogrd.npy')


# - ---------------------------------------------------------------------------
# BAKAR -----------------------------------------------------------------------
bakar=pd.read_csv('path/bakar.txt',\
                 sep=';',header=None)[:]
datebak = pd.date_range('1/1/1930','12/31/2020', freq='M')
bakar.index = datebak
bakar.loc[bakar[3] == 1, 1] = np.nan
bak = bakar[1]
bak = bak.replace(-99999, np.nan)
valid_counts_per_year = bak.groupby(bak.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    bak[bak.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,2,20]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = bak - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,1,43]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = bak - (alpha * era5_anomaly)
bak = ib_0.combine_first(ib_1)
# - -
bak_y = bak.resample('Y').mean()
bak_y = bak_y['1950':]
bak_y = bak_y.interpolate(method='linear')
# GIA
trend = -0.14
time_passed = np.arange(bak_y.shape[0])[:]
cumulative_trend = time_passed * trend
bak_y = bak_y - cumulative_trend
bak_y2 = bak_y.dropna()
# GRD
grd = sea_barystatic[:,270,389]
grd = pd.Series(grd, index=datebary)
bak_y = bak_y - grd
bak_y = bak_y.dropna()

sea = bak_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean5 = imfs_sum / num_ensembles
imfs_mean5[4] = imfs_mean5[4] - np.mean(imfs_mean5[4])
imfs_mean5[3] = imfs_mean5[3] - np.mean(imfs_mean5[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Bakar", y=0.83)
for n, imf in enumerate(imfs_mean5):
    plt.subplot(len(imfs_mean5)+1, 1, n+2)
    plt.plot(bak_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean5)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean5)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_bakar.npy', imfs_mean5)
#np.save('imfs_bakar_nogrd.npy', imfs_mean5)
imfs_bakar = np.load('path/imfs_bakar.npy')
imfs_bakar_nogrd = np.load('pathimfs_bakar_nogrd.npy')


# SPLIT GRADSKA LUKA ------------------------------------------------------------------
# -----------------------------------------------------------------------------
spl=pd.read_csv('path/split.txt',\
                 sep=';',header=None)[:]
datespl = pd.date_range('3/1/1954','12/31/2018', freq='M')
spl.index = datespl
spl = spl[1]
# IB
era20c_hPa = pressure_era20c[:,3,22]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = spl - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,4,47]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = spl - (alpha * era5_anomaly)
spl = ib_0.combine_first(ib_1)
# - -
spl_y = spl.resample('Y').mean()
# GIA
trend = -0.06
time_passed = np.arange(spl_y.shape[0])[:]
cumulative_trend = time_passed * trend
spl_y = spl_y - cumulative_trend
# GRD
grd = sea_barystatic[:,266,392]
grd = pd.Series(grd, index=datebary)
spl_y = spl_y - grd
spl_y = spl_y.dropna()

sea = spl_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean6 = imfs_sum / num_ensembles
imfs_mean6[4] = imfs_mean6[4] - np.mean(imfs_mean6[4])
imfs_mean6[3] = imfs_mean6[3] - np.mean(imfs_mean6[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Split", y=0.83)
for n, imf in enumerate(imfs_mean6):
    plt.subplot(len(imfs_mean6)+1, 1, n+2)
    plt.plot(spl_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean6)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean6)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_split.npy', imfs_mean6)
#np.save('imfs_split_nogrd.npy', imfs_mean6)
imfs_split = np.load('path/imfs_split.npy')
imfs_split_nogrd = np.load('path/imfs_split_nogrd.npy')


# DUBROVNIK -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
dub=pd.read_csv('path/dubrovnik.txt',\
                 sep=';',header=None)[:]
datedub = pd.date_range('1/1/1956','10/31/2018', freq='M')
dub.index = datedub
dub = dub[1]
dub = dub.replace(-99999, np.nan)
# IB
era20c_hPa = pressure_era20c[:,5,23]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = dub - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,7,50]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = dub - (alpha * era5_anomaly)
dub = ib_0.combine_first(ib_1)
# - -
dub_y = dub.resample('Y').mean()
# GIA
trend = -0.04
time_passed = np.arange(dub_y.shape[0])[:]
cumulative_trend = time_passed * trend
dub_y = dub_y - cumulative_trend
# GRD
grd = sea_barystatic[:,265,396]
grd = pd.Series(grd, index=datebary)
dub_y = dub_y - grd
dub_y = dub_y.dropna()

sea = dub_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean7 = imfs_sum / num_ensembles
imfs_mean7[4] = imfs_mean7[4] - np.mean(imfs_mean7[4])
imfs_mean7[3] = imfs_mean7[3] - np.mean(imfs_mean7[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Dubrovnik", y=0.83)
for n, imf in enumerate(imfs_mean7):
    plt.subplot(len(imfs_mean7)+1, 1, n+2)
    plt.plot(dub_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean7)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean7)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_dubrovnik.npy', imfs_mean7)
#np.save('imfs_dubrovnik_nogrd.npy', imfs_mean7)
imfs_dubrovnik = np.load('path/imfs_dubrovnik.npy')
imfs_dubrovnik_nogrd = np.load('path/imfs_dubrovnik_nogrd.npy')


# ZADAR -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
zad=pd.read_csv('path/zadar.txt',\
                 sep=';',header=None)[:]
datezad = pd.date_range('6/1/1994','12/31/2018', freq='M')
zad.index = datezad
zad = zad[1]
zad = zad.replace(-99999, np.nan)
valid_counts_per_year = zad.groupby(zad.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    zad[zad.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,3,21]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = zad - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,4,44]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = zad - (alpha * era5_anomaly)
zad = ib_0.combine_first(ib_1)
# - -
zad_y = zad.resample('Y').mean()
# GIA
trend = -0.08
time_passed = np.arange(zad_y.shape[0])[:]
cumulative_trend = time_passed * trend
zad_y = zad_y - cumulative_trend
# GRD
grd = sea_barystatic[:,268,396]
grd = pd.Series(grd, index=datebary)
zad_y = zad_y - grd
zad_y = zad_y.dropna()

sea = zad_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean23 = imfs_sum / num_ensembles
imfs_mean23[2] = imfs_mean23[2] - np.mean(imfs_mean23[2])
imfs_mean23[3] = imfs_mean23[3] - np.mean(imfs_mean23[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Zadar", y=0.83)
for n, imf in enumerate(imfs_mean23):
    plt.subplot(len(imfs_mean23)+1, 1, n+2)
    plt.plot(zad_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean23)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean23)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_zadar.npy', imfs_mean23)
#np.save('imfs_zadar_nogrd.npy', imfs_mean23)
imfs_zadar = np.load('path/imfs_zadar.npy')
imfs_zadar_nogrd = np.load('path/imfs_zadar_nogrd.npy')


# BAR -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
bar=pd.read_csv('path/bar.txt',\
                 sep=';',header=None)[:]
datebar = pd.date_range('7/1/1964','1/31/1991', freq='M')
bar.index = datebar
bar.loc[bar[3] == 1, 1] = np.nan
bar = bar[1]
bar = bar.replace(-99999, np.nan)
valid_counts_per_year = bar.groupby(bar.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    bar[bar.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,5,24]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = bar - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,8,52]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = bar - (alpha * era5_anomaly)
bar = ib_0.combine_first(ib_1)
# - -
bar_y = bar.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
bar_y = interpolate_short_gaps(bar_y.copy())
# GIA
trend = -0.06
time_passed = np.arange(bar_y.shape[0])[:]
cumulative_trend = time_passed * trend
bar_y = bar_y - cumulative_trend
# GRD
grd = sea_barystatic[:,264,398]
grd = pd.Series(grd, index=datebary)
bar_y = bar_y - grd
bar_y = bar_y.dropna()

sea = bar_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean24 = imfs_sum / num_ensembles
imfs_mean24[2] = imfs_mean24[2] - np.mean(imfs_mean24[2])
imfs_mean24[3] = imfs_mean24[3] - np.mean(imfs_mean24[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Bar", y=0.83)
for n, imf in enumerate(imfs_mean24):
    plt.subplot(len(imfs_mean24)+1, 1, n+2)
    plt.plot(bar_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean24)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean24)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_bar.npy', imfs_mean24)
#np.save('imfs_bar_nogrd.npy', imfs_mean24)
imfs_bar = np.load('path/imfs_bar.npy')
imfs_bar_nogrd = np.load('path/imfs_bar_nogrd.npy')


# - - - - - - - - - - - - - - - - 

series1 = [(tri_y.index[:], ((imfs_trieste[1])[:])/10, 'orange', 'Trieste'),
          (ven_y.index[:], ((imfs_venice[1])[:])/10, 'blue', 'Venice'),
          (rav_y.index[:], ((imfs_ravenna[1])[:])/10, 'green', 'Porto Corsini'),
          (rov_y.index[:], ((imfs_rovinj[1])[:])/10, 'red', 'Rovinj'),
          (bak_y[:].index, ((imfs_bakar[1])[:])/10, 'magenta', 'Bakar'),
          (spl_y[:].index, ((imfs_split[1])[:])/10, 'black', 'Split'),
          (dub_y.index[:], ((imfs_dubrovnik[1])[:])/10, 'cyan', 'Dubrovnik'),
          (rav_y_old.index[:], ((imfs_ravenna_old[1])[:])/10, 'green', ''),
          (zad_y.index[:], ((imfs_zadar[1])[:])/10, 'gold', 'Zadar'),
          (bar_y.index[:], ((imfs_bar[1])[:])/10, 'violet', 'Bar')
          ]

plt.figure(figsize=(26,8), dpi=300)
for serie in series1:
    idx, data, color, label = serie
    idx = idx - pd.DateOffset(months=6)
    plt.plot(idx, data, label=label, color=color, linewidth=2)
    maxima = argrelextrema(data, np.greater)
    minima = argrelextrema(data, np.less)
    for max_idx in maxima[0]:
        plt.axvspan(idx[max_idx] - timedelta(365.25/2), idx[max_idx] + timedelta(365.25/2), color='r', alpha=0.1)
    for min_idx in minima[0]:
        plt.axvspan(idx[min_idx] - timedelta(365.25/2), idx[min_idx] + timedelta(365.25/2), color='b', alpha=0.1)
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))  
plt.gca().xaxis.set_minor_locator(mdates.YearLocator()) 
plt.xlabel('time', fontsize=16)
plt.ylabel('sea level (cm)', fontsize=16)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
date_bande = ['1991.5', '1997.5', '2006.5', '2011.5', '2017.5']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(adria_basin.index, adria_basin*100, linestyle='--', linewidth=3, label='Adriatic mean from SA')
plt.legend(handlelength=1, fontsize=16, framealpha=1, loc='lower left', ncol=9, facecolor='white')
plt.show()

dfs = [pd.DataFrame(data, index=idx) for idx, data, _, _ in series1]
aligned_dfs = pd.concat(dfs, axis=1)
mean_series = aligned_dfs.mean(axis=1)
mean_series = mean_series.shift(freq='-11M')
max_series = aligned_dfs.max(axis=1)
min_series = aligned_dfs.min(axis=1)

plt.figure(figsize=(17,5), dpi=100)
maxima_mean = argrelextrema(mean_series.values, np.greater)[0]
minima_mean = argrelextrema(mean_series.values, np.less)[0]
combined = sorted(list(maxima_mean) + list(minima_mean))
combined = [0] + combined + [len(mean_series)-1]
colors = ["#56B4E9","#E69F00"]
for i in range(len(combined)-1):
    start_idx = combined[i]
    end_idx = combined[i+1]
    plt.axvspan(mean_series.index[start_idx], mean_series.index[end_idx], color=colors[i % 2], alpha=0.3)
for max_idx in maxima_mean:
    plt.axvspan(mean_series.index[max_idx] - timedelta(365.25/2),
                mean_series.index[max_idx] + timedelta(365.25/2),
                color='white', alpha=1)
for min_idx in minima_mean:
    plt.axvspan(mean_series.index[min_idx] - timedelta(365.25/2),
                mean_series.index[min_idx] + timedelta(365.25/2),
                color='white', alpha=1)
std_dev_series = aligned_dfs.std(axis=1)
std_dev_series = std_dev_series.shift(freq='-11M')
plt.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4)
plt.plot(mean_series.index, mean_series, color='black', label = r'TG ensemble mean $\pm 1\sigma$', linewidth=2)
start_year = datetime(1900, 1, 1)
end_year = datetime(2018, 1, 31)
plt.gca().set_xlim([start_year, end_year])
plt.gca().xaxis.set_major_locator(mdates.YearLocator(10))
plt.gca().xaxis.set_minor_locator(mdates.YearLocator(1))
plt.xlabel('time', fontsize=20)
plt.ylabel('sea level (cm)', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
date_bande = ['1991', '1998', '2006', '2010', '2017']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(adria_basin.index, adria_basin*100, linestyle='--', linewidth=3, label='SA basin mean', color='red')
plt.title('Adriatic', fontsize=20)
plt.legend(handlelength=1.5, fontsize=20, framealpha=1, loc='lower left', ncol=9, facecolor='white')
plt.show()

print("Maxima dates:")
for idx in maxima_mean:
    print(mean_series.index[idx].date())
print("\nMinima dates:")
for idx in minima_mean:
    print(mean_series.index[idx].date())

series1_nogrd = [(tri_y2.index[:], ((imfs_trieste_nogrd[1])[:])/10, 'orange', 'Trieste'),
          (ven_y2.index[:], ((imfs_venice_nogrd[1])[:])/10, 'blue', 'Venice'),
          (rav_y.index[:], ((imfs_ravenna_nogrd[1])[:])/10, 'green', 'Porto Corsini'),
          (rov_y.index[:], ((imfs_rovinj_nogrd[1])[:])/10, 'red', 'Rovinj'),
          (bak_y2[:].index, ((imfs_bakar_nogrd[1])[:])/10, 'magenta', 'Bakar'),
          (spl_y[:].index, ((imfs_split_nogrd[1])[:])/10, 'black', 'Split'),
          (dub_y.index[:], ((imfs_dubrovnik_nogrd[1])[:])/10, 'cyan', 'Dubrovnik'),
          (rav_y_old.index[:], ((imfs_ravenna_old_nogrd[1])[:])/10, 'green', ''),
          (zad_y.index[:], ((imfs_zadar_nogrd[1])[:])/10, 'gold', 'Zadar'),
          (bar_y.index[:], ((imfs_bar_nogrd[1])[:])/10, 'violet', 'Bar')
          ]


# - - - - - - -    IONIAN SEA

# PREVEZA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
pre=pd.read_csv('path/preveza.txt',\
                 sep=';',header=None)[:]
datepre = pd.date_range('1/1/1969','11/30/2022', freq='M')
pre.index = datepre
pre = pre[1]
pre = pre.replace(-99999, np.nan)
valid_counts_per_year = pre.groupby(pre.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    pre[pre.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,8,25]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = pre - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,14,55]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = pre - (alpha * era5_anomaly)
pre = ib_0.combine_first(ib_1)
# --
pre_y = pre.resample('Y').mean()
pre_y = pre_y['1980-12-31':]
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
pre_y = interpolate_short_gaps(pre_y.copy())
# GIA
trend = -0.04
time_passed = np.arange(pre_y.shape[0])[:]
cumulative_trend = time_passed * trend
pre_y = pre_y - cumulative_trend
pre_y2 = pre_y.dropna()
# GRD
grd = sea_barystatic[:,257,401]
grd = pd.Series(grd, index=datebary)
pre_y = pre_y - grd
pre_y = pre_y.dropna()

sea = pre_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean8 = imfs_sum / num_ensembles
imfs_mean8[4] = imfs_mean8[4] - np.mean(imfs_mean8[4])
imfs_mean8[3] = imfs_mean8[3] - np.mean(imfs_mean8[3])
imfs_mean8[2] = imfs_mean8[2] - np.mean(imfs_mean8[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Preveza", y=0.83)
for n, imf in enumerate(imfs_mean8):
    plt.subplot(len(imfs_mean8)+1, 1, n+2)
    plt.plot(pre_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean8)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean8)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_preveza.npy', imfs_mean8)
#np.save('imfs_preveza_nogrd.npy', imfs_mean8)
imfs_preveza = np.load('path/imfs_preveza.npy')
imfs_preveza_nogrd = np.load('path/imfs_preveza_nogrd.npy')


# LEVKAS -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
lev=pd.read_csv('path/levkas.txt',\
                 sep=';',header=None)[:]
datelev = pd.date_range('3/1/1969','12/31/2022', freq='M')
lev.index = datelev
lev = lev[1]
lev = lev.replace(-99999, np.nan)
valid_counts_per_year = lev.groupby(lev.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    lev[lev.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,8,25]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = lev - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,15,55]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = lev - (alpha * era5_anomaly)
lev = ib_0.combine_first(ib_1)
# --
lev_y = lev.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
lev_y = interpolate_short_gaps(lev_y.copy())
# GIA
trend = -0.02
time_passed = np.arange(lev_y.shape[0])[:]
cumulative_trend = time_passed * trend
lev_y = lev_y - cumulative_trend
lev_y2 = lev_y.dropna()
# GRD
grd = sea_barystatic[:,257,401]
grd = pd.Series(grd, index=datebary)
lev_y = lev_y - grd
lev_y = lev_y.dropna()

sea = lev_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean9 = imfs_sum / num_ensembles
imfs_mean9[3] = imfs_mean9[3] - np.mean(imfs_mean9[3])
imfs_mean9[2] = imfs_mean9[2] - np.mean(imfs_mean9[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Levkas", y=0.83)
for n, imf in enumerate(imfs_mean9):
    plt.subplot(len(imfs_mean9)+1, 1, n+2)
    plt.plot(lev_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean9)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean9)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_levkas.npy', imfs_mean9)
#np.save('imfs_levkas_nogrd.npy', imfs_mean9)
imfs_levkas = np.load('path/imfs_levkas.npy')
imfs_levkas_nogrd = np.load('path/imfs_levkas_nogrd.npy')


# VALLETTA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
val=pd.read_csv('path/valletta.txt',\
                 sep=';',header=None)[:]
dateval = pd.date_range('11/1/1988','12/31/2022', freq='M')
val.index = dateval
val = val[1]
val = val['1989':]
val = val.replace(-99999, np.nan)
valid_counts_per_year = val.groupby(val.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    val[val.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,11,20]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = val - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,20,43]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = val - (alpha * era5_anomaly)
lev = ib_0.combine_first(ib_1)
# --
val_y = val.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
val_y = interpolate_short_gaps(val_y.copy())
# GIA
trend = 0.30
time_passed = np.arange(val_y.shape[0])[:]
cumulative_trend = time_passed * trend
val_y = val_y - cumulative_trend
val_y2 = val_y.dropna()
# GRD
grd = sea_barystatic[:,251,391]
grd = pd.Series(grd, index=datebary)
val_y = val_y - grd
val_y = val_y.dropna()

sea = val_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean10 = imfs_sum / num_ensembles
imfs_mean10[3] = imfs_mean10[3] - np.mean(imfs_mean10[3])
imfs_mean10[2] = imfs_mean10[2] - np.mean(imfs_mean10[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("La Valetta", y=0.83)
for n, imf in enumerate(imfs_mean10):
    plt.subplot(len(imfs_mean10)+1, 1, n+2)
    plt.plot(val_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean10)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean10)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_valletta.npy', imfs_mean10)
#np.save('imfs_valletta_nogrd.npy', imfs_mean10)
imfs_valletta = np.load('path/imfs_valletta.npy')
imfs_valletta_nogrd = np.load('path/imfs_valletta_nogrd.npy')


# KATAKOLON -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
kat=pd.read_csv('path/katakolon.txt',\
                 sep=';',header=None)[:]
datekat = pd.date_range('1/1/1969','11/30/2022', freq='M')
kat.index = datekat
kat = kat[1]
kat = kat.replace(-99999, np.nan)
valid_counts_per_year = kat.groupby(kat.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    kat[kat.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,9,26]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = kat - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,17,57]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = kat - (alpha * era5_anomaly)
kat = ib_0.combine_first(ib_1)
# --
kat_y = kat.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
kat_y = interpolate_short_gaps(kat_y.copy())
kat_y = kat_y['1969':]
# GIA
trend = 0.07
time_passed = np.arange(kat_y.shape[0])[:]
cumulative_trend = time_passed * trend
kat_y = kat_y - cumulative_trend
kat_y2 = kat_y.dropna()
# GRD
grd = sea_barystatic[:,255,402]
grd = pd.Series(grd, index=datebary)
kat_y = kat_y - grd
kat_y = kat_y.dropna()

sea = kat_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean11 = imfs_sum / num_ensembles
imfs_mean11[3] = imfs_mean11[3] - np.mean(imfs_mean11[3])
imfs_mean11[2] = imfs_mean11[2] - np.mean(imfs_mean11[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Katakolon", y=0.83)
for n, imf in enumerate(imfs_mean11):
    plt.subplot(len(imfs_mean11)+1, 1, n+2)
    plt.plot(kat_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean11)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean11)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_katakolon.npy', imfs_mean11)
#np.save('imfs_katakolon_nogrd.npy', imfs_mean11)
imfs_katakolon = np.load('path/imfs_katakolon.npy')
imfs_katakolon_nogrd = np.load('path/imfs_katakolon_nogrd.npy')


# KALAMAI -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
kal=pd.read_csv('path/kalamai.txt',\
                 sep=';',header=None)[:]
datekal = pd.date_range('1/1/1969','12/31/2019', freq='M')
kal.index = datekal
kal = kal[1]
kal = kal.replace(-99999, np.nan)
valid_counts_per_year = kal.groupby(kal.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    kal[kal.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,9,27]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = kal - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,18,58]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = kal - (alpha * era5_anomaly)
kal = ib_0.combine_first(ib_1)
# --
kal_y = kal.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
kal_y = interpolate_short_gaps(kal_y.copy())
# GIA
trend = 0.11
time_passed = np.arange(kal_y.shape[0])[:]
cumulative_trend = time_passed * trend
kal_y = kal_y - cumulative_trend
# GRD
grd = sea_barystatic[:,254,404]
grd = pd.Series(grd, index=datebary)
kal_y = kal_y - grd
kal_y = kal_y.dropna()
kal_y = kal_y['1990':]

sea = kal_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean25 = imfs_sum / num_ensembles
imfs_mean25[3] = imfs_mean25[3] - np.mean(imfs_mean25[3])
imfs_mean25[2] = imfs_mean25[2] - np.mean(imfs_mean25[2])
imfs_mean25[1] = imfs_mean25[1] - np.mean(imfs_mean25[1])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Kalamai", y=0.83)
for n, imf in enumerate(imfs_mean25):
    plt.subplot(len(imfs_mean25)+1, 1, n+2)
    plt.plot(kal_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean25)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean25)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_kalamai.npy', imfs_mean25)
#np.save('imfs_kalamai_nogrd.npy', imfs_mean25)
imfs_kalamai = np.load('path/imfs_kalamai.npy')
imfs_kalamai_nogrd = np.load('path/imfs_kalamai_nogrd.npy')


# - - - - - - - - - - - - - - - - 
 
series2 = [(pre_y.index[:], ((imfs_preveza[1])[:])/10, '#E69F00', 'Preveza'),
          (lev_y.index[:], ((imfs_levkas[1])[:])/10, '#009E73', 'Levkas'),
          (kat_y.index[:], ((imfs_katakolon[1])[:])/10, '#D55E00', 'Katakolon'),
          (val_y.index[:], ((imfs_valletta[1])[:])/10, 'black', 'La Valletta'),
          (kal_y.index[:], ((imfs_kalamai[1])[:])/10, '#CC79A7', 'Kalamai')
          ]

plt.figure(figsize=(17,6), dpi=100)
ax = plt.gca()
for serie in series2:
    idx, data, color, label = serie
    idx = idx - pd.DateOffset(months=11)
    plt.plot(idx, data, label=label, color=color, linewidth=3)
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))  
plt.gca().xaxis.set_minor_locator(mdates.YearLocator()) 
plt.xlabel('time', fontsize=18)
plt.ylabel('IMF2 sea level (cm)', fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
date_bande = ['1987','1990', '1997', '2007', '2010', '2016','2019']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=3)
plt.plot(ion_basin_combined.index, ion_basin_combined*100, linestyle='--', linewidth=3, label='Ionian mean from SA', color='#56B4E9')  # Convertito da m a cm
plt.axhline(y=0, color='black', linestyle='--', linewidth=1)
ax.set_ylim([-7.2, 4.6])
plt.legend(handlelength=1, fontsize=18, framealpha=1, loc='lower left', ncol=3, facecolor='white')
plt.show()

dfs = [pd.DataFrame(data, index=idx) for idx, data, _, _ in series2]
aligned_dfs = pd.concat(dfs, axis=1)
mean_series = aligned_dfs.mean(axis=1)
mean_series = mean_series.shift(freq='-11M')
max_series = aligned_dfs.max(axis=1)
min_series = aligned_dfs.min(axis=1)

plt.figure(figsize=(17,5), dpi=300)
maxima_mean = argrelextrema(mean_series.values, np.greater)[0]
minima_mean = argrelextrema(mean_series.values, np.less)[0]
combined = sorted(list(maxima_mean) + list(minima_mean))
combined = [0] + combined + [len(mean_series)-1]
colors = ["#E69F00","#56B4E9"]
for i in range(len(combined)-1):
    start_idx = combined[i]
    end_idx = combined[i+1]
    plt.axvspan(mean_series.index[start_idx], mean_series.index[end_idx], color=colors[i % 2], alpha=0.3)
for max_idx in maxima_mean:
    plt.axvspan(mean_series.index[max_idx] - timedelta(365.25/2),
                mean_series.index[max_idx] + timedelta(365.25/2),
                color='white', alpha=1)
for min_idx in minima_mean:
    plt.axvspan(mean_series.index[min_idx] - timedelta(365.25/2),
                mean_series.index[min_idx] + timedelta(365.25/2),
                color='white', alpha=1)
std_dev_series = aligned_dfs.std(axis=1)
std_dev_series = std_dev_series.shift(freq='-11M')
plt.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4)
plt.plot(mean_series.index, mean_series, color='black', label = r'TG ensemble mean $\pm 1\sigma$', linewidth=2)
start_year = datetime(1969, 1, 1)
end_year = datetime(2018, 1, 31)
plt.gca().set_xlim([start_year, end_year])
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))
plt.gca().xaxis.set_minor_locator(mdates.YearLocator(1))
plt.xlabel('time', fontsize=20)
plt.ylabel('sea level (cm)', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
date_bande = ['1990', '1998', '2007', '2010', '2016']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(ion_basin_combined.index, ion_basin_combined*100, linestyle='--', linewidth=3, label='SA basin mean', color='red')
plt.title('Ionian', fontsize=20)
plt.legend(handlelength=1.5, fontsize=20, framealpha=1, loc='lower left', ncol=9, facecolor='white')
plt.show()

print("Maxima dates:")
for idx in maxima_mean:
    print(mean_series.index[idx].date())
print("\nMinima dates:")
for idx in minima_mean:
    print(mean_series.index[idx].date())

series2_nogrd = [(pre_y2.index[:], ((imfs_preveza_nogrd[1])[:])/10, 'orange', 'Preveza'),
          (lev_y2.index[:], ((imfs_levkas_nogrd[1])[:])/10, 'green', 'Levkas'),
          (kat_y2.index[:], ((imfs_katakolon_nogrd[1])[:])/10, 'red', 'Katakolon'),
          (val_y2.index[:], ((imfs_valletta_nogrd[1])[:])/10, 'black', 'La Valletta'),
          (kal_y.index[:], ((imfs_kalamai_nogrd[1])[:])/10, 'magenta', 'Kalamai')
          ]


# - - - - - - -    LEVANTINE BASIN

# ALEXANDRIA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
ale=pd.read_csv('path/alexandria.txt',\
                 sep=';',header=None)[:]
dateale = pd.date_range('1/1/1944','11/30/2006', freq='M')
ale.index = dateale
ale = ale[1]
ale = ale.replace(-99999, np.nan)
valid_counts_per_year = ale.groupby(ale.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    ale[ale.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,15,33]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = ale - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,30,74]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = ale - (alpha * era5_anomaly)
ale = ib_0.combine_first(ib_1)
# --
ale_y = ale.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
ale_y = interpolate_short_gaps(ale_y.copy())
# GIA
trend = -0.01
time_passed = np.arange(ale_y.shape[0])[:]
cumulative_trend = time_passed * trend
ale_y = ale_y - cumulative_trend
# GRD
grd = sea_barystatic[:,242,419]
grd = pd.Series(grd, index=datebary)
ale_y = ale_y - grd
ale_y = ale_y.dropna()

sea = ale_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean12 = imfs_sum / num_ensembles
imfs_mean12[3] = imfs_mean12[3] - np.mean(imfs_mean12[3])
imfs_mean12[4] = imfs_mean12[4] - np.mean(imfs_mean12[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Alexandria", y=0.83)
for n, imf in enumerate(imfs_mean12):
    plt.subplot(len(imfs_mean12)+1, 1, n+2)
    plt.plot(ale_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean12)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean12)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_alexandria.npy', imfs_mean12)
#np.save('imfs_alexandria_nogrd.npy', imfs_mean12)
imfs_alexandria = np.load('path/imfs_alexandria.npy')
imfs_alexandria_nogrd = np.load('path/imfs_alexandria_nogrd.npy')


# ANTALYA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
# FROM OZTURK ET AL. 2018
# ANNUAL MEAN 1953, 1954, 1955 REMOVED AS STATED IN THE PAPER
ant = Dataset("path/antalya.nc")
ant.variables.keys()
ant = ant.variables['MSL_Antalya_Corrected'][:]
ant = pd.Series(ant)
dateant = pd.date_range('6/1/1935','11/30/2009', freq='M')
ant.index = dateant
ant = ant.replace(-9999, np.nan)
valid_counts_per_year = ant.groupby(ant.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    ant[ant.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,10,34]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = ant - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,18,75]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = ant - (alpha * era5_anomaly)
ant = ib_0.combine_first(ib_1)
# --
ant_y = ant.resample('Y').mean()
dates_to_replace = pd.to_datetime(['1953-12-31', '1954-12-31', '1955-12-31'])
for date in dates_to_replace:
    ant_y.loc[date] = np.nan
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
ant_y = interpolate_short_gaps(ant_y.copy()) 
# GIA
trend = -0.10
time_passed = np.arange(ant_y.shape[0])[:]
cumulative_trend = time_passed * trend
ant_y = ant_y - cumulative_trend
# GRD
grd = sea_barystatic[:,253,421]
grd = pd.Series(grd, index=datebary)
ant_y = ant_y - grd
ant_y_new = ant_y['1986':'2008']
ant_y = ant_y['1936':'1975']
ant_y = ant_y.dropna()
ant_y_new = ant_y_new.dropna()

sea = ant_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean13 = imfs_sum / num_ensembles
imfs_mean13[3] = imfs_mean13[3] - np.mean(imfs_mean13[3])
imfs_mean13[2] = imfs_mean13[2] - np.mean(imfs_mean13[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Antalya", y=0.83)
for n, imf in enumerate(imfs_mean13):
    plt.subplot(len(imfs_mean13)+1, 1, n+2)
    plt.plot(ant_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean13)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean13)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_antalya.npy', imfs_mean13)
#np.save('imfs_antalya_nogrd.npy', imfs_mean13)
imfs_antalya = np.load('path/imfs_antalya.npy')
imfs_antalya_nogrd = np.load('path/imfs_antalya_nogrd.npy')


#  ANTALYA NEW -----------------------
sea = ant_y_new.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean26 = imfs_sum / num_ensembles
imfs_mean26[3] = imfs_mean26[3] - np.mean(imfs_mean26[3])
imfs_mean26[2] = imfs_mean26[2] - np.mean(imfs_mean26[2])
imfs_mean26[1] = imfs_mean26[1] - np.mean(imfs_mean26[1])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Antalya", y=0.83)
for n, imf in enumerate(imfs_mean26):
    plt.subplot(len(imfs_mean26)+1, 1, n+2)
    plt.plot(ant_y_new.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean26)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean26)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_antalya_new.npy', imfs_mean26)
#np.save('imfs_antalya_new_nogrd.npy', imfs_mean26)
imfs_antalya_new = np.load('path/imfs_antalya_new.npy')
imfs_antalya_new_nogrd = np.load('path/imfs_antalya_new_nogrd.npy')


# HADERA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
had=pd.read_csv('path/hadera.txt',\
                 sep=';',header=None)[:]
datehad = pd.date_range('6/1/1992','12/31/2022', freq='M')
had.index = datehad
had = had[1]
had = had.replace(-99999, np.nan)
valid_counts_per_year = had.groupby(had.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    had[had.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,13,38]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = had - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,27,84]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = had - (alpha * era5_anomaly)
had = ib_0.combine_first(ib_1)
# --
had_y = had.resample('Y').mean()
for date in dates_to_replace:
    had_y.loc[date] = np.nan
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
had_y = interpolate_short_gaps(had_y.copy())
had_y = had_y['1994':]
# GIA
trend = 0.02
time_passed = np.arange(had_y.shape[0])[:]
cumulative_trend = time_passed * trend
had_y = had_y - cumulative_trend
had_y2 = had_y.dropna()
# GRD
grd = sea_barystatic[:,244,429]
grd = pd.Series(grd, index=datebary)
had_y = had_y - grd
had_y = had_y.dropna()

sea = had_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean14 = imfs_sum / num_ensembles
imfs_mean14[3] = imfs_mean14[3] - np.mean(imfs_mean14[3])
imfs_mean14[2] = imfs_mean14[2] - np.mean(imfs_mean14[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Hadera", y=0.83)
for n, imf in enumerate(imfs_mean14):
    plt.subplot(len(imfs_mean14)+1, 1, n+2)
    plt.plot(had_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean14)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean14)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_hadera.npy', imfs_mean14)
#np.save('imfs_hadera_nogrd.npy', imfs_mean14)
imfs_hadera = np.load('path/imfs_hadera.npy')
imfs_hadera_nogrd = np.load('path/imfs_hadera_nogrd.npy')


# PORT SAID -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
said=pd.read_csv('path/portsaid.txt',\
                 sep=';',header=None)[:]
datesaid = pd.date_range('1/1/1923','12/31/1946', freq='M')
said.index = datesaid
said = said[1]
said = said.replace(-99999, np.nan)
# IB
era20c_hPa = pressure_era20c[:,14,36]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = said - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,29,79]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = said - (alpha * era5_anomaly)
said = ib_0.combine_first(ib_1)
# --
said_y = said.resample('Y').mean()
# GIA
trend = -0.06
time_passed = np.arange(said_y.shape[0])[:]
cumulative_trend = time_passed * trend
said_y = said_y - cumulative_trend
# GRD
grd = sea_barystatic[:,242,424]
grd = pd.Series(grd, index=datebary)
said_y = said_y - grd
said_y = said_y.dropna()

sea = said_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean27 = imfs_sum / num_ensembles
imfs_mean27[3] = imfs_mean27[3] - np.mean(imfs_mean27[3])
imfs_mean27[2] = imfs_mean27[2] - np.mean(imfs_mean27[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Port Said", y=0.83)
for n, imf in enumerate(imfs_mean27):
    plt.subplot(len(imfs_mean27)+1, 1, n+2)
    plt.plot(said_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean27)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean27)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_portsaid.npy', imfs_mean27)
#np.save('imfs_portsaid_nogrd.npy', imfs_mean27)
imfs_portsaid = np.load('path/imfs_portsaid.npy')
imfs_portsaid_nogrd = np.load('path/imfs_portsaid_nogrd.npy')

# - - - - - - - - - - - - - - - - 
 
series3 = [(ant_y.index[:], ((imfs_antalya[1])[:])/10, 'black', 'Antalya'),
          (ale_y.index[:62], ((imfs_alexandria[1])[:62])/10, 'green', 'Alexandria'),
          (had_y.index[:], ((imfs_hadera[1])[:])/10, 'red', 'Hadera'),
          (ant_y_new.index[:], ((imfs_antalya_new[1])[:])/10, 'black', ''),
          (said_y.index[:], ((imfs_portsaid[1])[:])/10, 'orange', 'Port Said')
          ]

plt.figure(figsize=(26,8), dpi=300)
for serie in series3:
    idx, data, color, label = serie
    idx = idx - pd.DateOffset(months=6)
    plt.plot(idx, data, label=label, color=color, linewidth=2)
    maxima = argrelextrema(data, np.greater)
    minima = argrelextrema(data, np.less)
    for max_idx in maxima[0]:
        plt.axvspan(idx[max_idx] - timedelta(365.25/2), idx[max_idx] + timedelta(365.25/2), color='r', alpha=0.1)
    for min_idx in minima[0]:
        plt.axvspan(idx[min_idx] - timedelta(365.25/2), idx[min_idx] + timedelta(365.25/2), color='b', alpha=0.1)
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))  
plt.gca().xaxis.set_minor_locator(mdates.YearLocator()) 
plt.xlabel('time', fontsize=16)
plt.ylabel('sea level (cm)', fontsize=16)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
date_bande = ['1991.5', '1997.5', '2006.5', '2011.5', '2017.5']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(lev_basin.index, lev_basin*100, linestyle='--', linewidth=3, label='Ionian mean from SA')
plt.legend(handlelength=1, fontsize=16, framealpha=1, loc='lower left', ncol=9, facecolor='white')
plt.show()

dfs = [pd.DataFrame(data, index=idx) for idx, data, _, _ in series3]
aligned_dfs = pd.concat(dfs, axis=1)
mean_series = aligned_dfs.mean(axis=1)
mean_series = mean_series.shift(freq='-11M')
max_series = aligned_dfs.max(axis=1)
min_series = aligned_dfs.min(axis=1)

plt.figure(figsize=(17,5), dpi=300)
maxima_mean = argrelextrema(mean_series.values, np.greater)[0]
minima_mean = argrelextrema(mean_series.values, np.less)[0]
index_2000 = mean_series[mean_series.index.year == 2000].index
index_2002 = mean_series[mean_series.index.year == 2002].index
index_to_remove = list(index_2000) + list(index_2002)
maxima_mean = [idx for idx in maxima_mean if mean_series.index[idx] not in index_to_remove]
minima_mean = [idx for idx in minima_mean if mean_series.index[idx] not in index_to_remove]
combined = sorted(list(maxima_mean) + list(minima_mean))
combined = [0] + combined + [len(mean_series)-1]
colors = ["#E69F00","#56B4E9"]
for i in range(len(combined)-1):
    start_idx = combined[i]
    end_idx = combined[i+1]
    plt.axvspan(mean_series.index[start_idx], mean_series.index[end_idx], color=colors[i % 2], alpha=0.3)
for max_idx in maxima_mean:
    plt.axvspan(mean_series.index[max_idx] - timedelta(365.25/2),
                mean_series.index[max_idx] + timedelta(365.25/2),
                color='white', alpha=1)
for min_idx in minima_mean:
    plt.axvspan(mean_series.index[min_idx] - timedelta(365.25/2),
                mean_series.index[min_idx] + timedelta(365.25/2),
                color='white', alpha=1)
std_dev_series = aligned_dfs.std(axis=1)
std_dev_series = std_dev_series.shift(freq='-11M')
plt.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4)
plt.plot(mean_series.index, mean_series, color='black', label = r'TG ensemble mean $\pm 1\sigma$', linewidth=2)
start_year = datetime(1923, 1, 1)
end_year = datetime(2018, 1, 31)
plt.gca().set_xlim([start_year, end_year])
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))
plt.gca().xaxis.set_minor_locator(mdates.YearLocator(1))
plt.xlabel('time', fontsize=20)
plt.ylabel('sea level (cm)', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
date_bande = ['1992', '1996', '2007', '2011', '2017']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(lev_basin.index, lev_basin*100, linestyle='--', linewidth=3, label='SA basin mean', color='red')
plt.title('Levantine', fontsize=20)
plt.legend(handlelength=1.5, fontsize=20, framealpha=1, loc='lower left', ncol=9, facecolor='white')
plt.show()

print("Maxima dates:")
for idx in maxima_mean:
    print(mean_series.index[idx].date())
print("\nMinima dates:")
for idx in minima_mean:
    print(mean_series.index[idx].date())

series3_nogrd = [(ant_y.index[:], ((imfs_antalya_nogrd[1])[:])/10, 'black', 'Antalya'),
          (ale_y.index[:62], ((imfs_alexandria_nogrd[1])[:62])/10, 'green', 'Alexandria'),
          (had_y2.index[:], ((imfs_hadera_nogrd[1])[:])/10, 'red', 'Hadera'),
          (ant_y_new.index[:], ((imfs_antalya_new_nogrd[1])[:])/10, 'black', ''),
          (said_y.index[:], ((imfs_portsaid_nogrd[1])[:])/10, 'orange', 'Port Said')
          ]


# - - - - - - -    AEGEAN SEA

# LEROS -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
ler=pd.read_csv('path/leros.txt',\
                 sep=';',header=None)[:]
dateler = pd.date_range('4/1/1969','12/31/2022', freq='M')
ler.index = dateler
ler = ler[1]
ler = ler.replace(-99999, np.nan)
valid_counts_per_year = ler.groupby(ler.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    ler[ler.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,9,31]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = ler - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,18,68]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = ler - (alpha * era5_anomaly)
ler = ib_0.combine_first(ib_1)
# --
ler_y = ler.resample('Y').mean()
ler_y = ler_y['1970':]
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
ler_y = interpolate_short_gaps(ler_y.copy())
# GIA
trend = 0.03
time_passed = np.arange(ler_y.shape[0])[:]
cumulative_trend = time_passed * trend
ler_y = ler_y - cumulative_trend
ler_y2 = ler_y.dropna()
# GRD
grd = sea_barystatic[:,254,413]
grd = pd.Series(grd, index=datebary)
ler_y = ler_y - grd
ler_y = ler_y.dropna()

sea = ler_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean15 = imfs_sum / num_ensembles
imfs_mean15[3] = imfs_mean15[3] - np.mean(imfs_mean15[3])
imfs_mean15[4] = imfs_mean15[4] - np.mean(imfs_mean15[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Leros", y=0.83)
for n, imf in enumerate(imfs_mean15):
    plt.subplot(len(imfs_mean15)+1, 1, n+2)
    plt.plot(ler_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean15)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean15)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_leros.npy', imfs_mean15)
#np.save('imfs_leros_nogrd.npy', imfs_mean15)
imfs_leros = np.load('path/imfs_leros.npy')
imfs_leros_nogrd = np.load('path/imfs_leros_nogrd.npy')


# KHIOS -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
khi=pd.read_csv('path/khios.txt',\
                 sep=';',header=None)[:]
datekhi = pd.date_range('1/1/1969','9/30/2015', freq='M')
khi.index = datekhi
khi = khi[1]
khi = khi.replace(-99999, np.nan)
valid_counts_per_year = khi.groupby(khi.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    khi[khi.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,8,30]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = khi - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,15,66]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = khi - (alpha * era5_anomaly)
khi = ib_0.combine_first(ib_1)
# --
khi_y = khi.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
khi_y = interpolate_short_gaps(khi_y.copy())
# GIA
trend = -0.04
time_passed = np.arange(khi_y.shape[0])[:]
cumulative_trend = time_passed * trend
khi_y = khi_y - cumulative_trend
# GRD
grd = sea_barystatic[:,256,412]
grd = pd.Series(grd, index=datebary)
khi_y = khi_y - grd
khi_y = khi_y.dropna()

sea = khi_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean16 = imfs_sum / num_ensembles
imfs_mean16[3] = imfs_mean16[3] - np.mean(imfs_mean16[3])
imfs_mean16[2] = imfs_mean16[2] - np.mean(imfs_mean16[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Khios", y=0.83)
for n, imf in enumerate(imfs_mean16):
    plt.subplot(len(imfs_mean16)+1, 1, n+2)
    plt.plot(khi_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean16)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean16)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_khios.npy', imfs_mean16)
#np.save('imfs_khios_nogrd.npy', imfs_mean16)
imfs_khios = np.load('path/imfs_khios.npy')
imfs_khios_nogrd = np.load('path/imfs_khios_nogrd.npy')


# ALEXANDROUPOLIS -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
alex=pd.read_csv('path/alexandroupolis.txt',\
                 sep=';',header=None)[:]
datealex = pd.date_range('1/1/1969','12/31/2022', freq='M')
alex.index = datealex
alex = alex[1]
alex = alex.replace(-99999, np.nan)
valid_counts_per_year = alex.groupby(alex.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    alex[alex.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,6,30]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = alex - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,10,66]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = alex - (alpha * era5_anomaly)
alex = ib_0.combine_first(ib_1)
# --
alex_y = alex.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
alex_y = interpolate_short_gaps(alex_y.copy())
# GIA
trend = -0.12
time_passed = np.arange(alex_y.shape[0])[:]
cumulative_trend = time_passed * trend
alex_y = alex_y - cumulative_trend
alex_y2 = alex_y.dropna()
# GRD
grd = sea_barystatic[:,261,411]
grd = pd.Series(grd, index=datebary)
alex_y = alex_y - grd
alex_y = alex_y.dropna()

sea = alex_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean17 = imfs_sum / num_ensembles
imfs_mean17[3] = imfs_mean17[3] - np.mean(imfs_mean17[3])
imfs_mean17[2] = imfs_mean17[2] - np.mean(imfs_mean17[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Alexandroupolis", y=0.83)
for n, imf in enumerate(imfs_mean17):
    plt.subplot(len(imfs_mean17)+1, 1, n+2)
    plt.plot(alex_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean17)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean17)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_alexandroupolis.npy', imfs_mean17)
#np.save('imfs_alexandroupolis_nogrd.npy', imfs_mean17)
imfs_alexandroupolis = np.load('path/imfs_alexandroupolis.npy')
imfs_alexandroupolis_nogrd = np.load('path/imfs_alexandroupolis_nogrd.npy')


# THESSALONIKI -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
the=pd.read_csv('path/thessaloniki.txt',\
                 sep=';',header=None)[:]
datethe = pd.date_range('1/1/1969','11/30/2019', freq='M')
the.index = datethe
the = the[1]
the = the.replace(-99999, np.nan)
valid_counts_per_year = the.groupby(the.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    the[the.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,6,27]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = the - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,11,60]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = the - (alpha * era5_anomaly)
the = ib_0.combine_first(ib_1)
# --
the_y = the.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
the_y = interpolate_short_gaps(the_y.copy())
# GIA
trend = -0.17
time_passed = np.arange(the_y.shape[0])[:]
cumulative_trend = time_passed * trend
the_y = the_y - cumulative_trend
# GRD
grd = sea_barystatic[:,261,405]
grd = pd.Series(grd, index=datebary)
the_y = the_y - grd
the_y = the_y.dropna()

sea = the_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean18 = imfs_sum / num_ensembles
imfs_mean18[3] = imfs_mean18[3] - np.mean(imfs_mean18[3])
imfs_mean18[2] = imfs_mean18[2] - np.mean(imfs_mean18[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Thessaloniki", y=0.83)
for n, imf in enumerate(imfs_mean18):
    plt.subplot(len(imfs_mean18)+1, 1, n+2)
    plt.plot(the_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean18)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean18)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_thessaloniki.npy', imfs_mean18)
#np.save('imfs_thessaloniki_nogrd.npy', imfs_mean18)
imfs_thessaloniki = np.load('path/imfs_thessaloniki.npy')
imfs_thessaloniki_nogrd = np.load('path/imfs_thessaloniki_nogrd.npy')


# KHALKIS -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
kha1=pd.read_csv('path/khalkis south.txt',\
                 sep=';',header=None)[:]
datekha1 = pd.date_range('9/1/1977','12/31/2022', freq='M')
kha1.index = datekha1
kha1 = kha1[1]
kha1 = kha1.replace(-99999, np.nan)
kha1 = kha1-np.mean(kha1)
kha2=pd.read_csv('path/khalkis north.txt',\
                 sep=';',header=None)[:]
datekha2 = pd.date_range('1/1/1969','12/31/2022', freq='M')
kha2.index = datekha2
kha2 = kha2[1]
kha2 = kha2.replace(-99999, np.nan)
kha2 = kha2['1977':]
kha2 = kha2-np.mean(kha2)
sum_series = kha1.add(kha2, fill_value=0)
mask = kha1.isna() ^ kha2.isna()
kha = np.where(mask, sum_series, sum_series/2)
kha = pd.Series(kha)
datekha = pd.date_range('1/1/1977','12/31/2022', freq='M')
kha.index = datekha
valid_counts_per_year = kha.groupby(kha.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    kha[kha.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,8,28]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = kha - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,15,61]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = kha - (alpha * era5_anomaly)
kha = ib_0.combine_first(ib_1)
# --
kha_y = kha.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
kha_y = interpolate_short_gaps(kha_y.copy())
# GIA
trend = -0.05
time_passed = np.arange(kha_y.shape[0])[:]
cumulative_trend = time_passed * trend
kha_y = kha_y - cumulative_trend
kha_y2 = kha_y.dropna()
# GRD
grd = sea_barystatic[:,256,407]
grd = pd.Series(grd, index=datebary)
kha_y = kha_y - grd
kha_y = kha_y.dropna()

sea = kha_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean19 = imfs_sum / num_ensembles
imfs_mean19[3] = imfs_mean19[3] - np.mean(imfs_mean19[3])
imfs_mean19[4] = imfs_mean19[4] - np.mean(imfs_mean19[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Khalkis", y=0.83)
for n, imf in enumerate(imfs_mean19):
    plt.subplot(len(imfs_mean19)+1, 1, n+2)
    plt.plot(kha_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean19)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean19)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_khalkis.npy', imfs_mean19)
#np.save('imfs_khalkis_nogrd.npy', imfs_mean19)
imfs_khalkis = np.load('path/imfs_khalkis.npy')
imfs_khalkis_nogrd = np.load('path/imfs_khalkis_nogrd.npy')


# PIRAIEVS -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
pir=pd.read_csv('path/piraievs.txt',\
                 sep=';',header=None)[:]
datepir = pd.date_range('1/1/1969','12/31/2022', freq='M')
pir.index = datepir
pir.loc[pir[3] == 1, 1] = np.nan
pir = pir[1]
pir = pir.replace(-99999, np.nan)
valid_counts_per_year = pir.groupby(pir.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    pir[pir.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,9,28]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = pir - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,16,61]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = pir - (alpha * era5_anomaly)
pir = ib_0.combine_first(ib_1)
# --
pir_y = pir.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
pir_y = interpolate_short_gaps(pir_y.copy())
# GIA IS ZERO
pir_y2 = pir_y.dropna()
# GRD
grd = sea_barystatic[:,255,407]
grd = pd.Series(grd, index=datebary)
pir_y = pir_y - grd
pir_y = pir_y.dropna()

sea = pir_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean20 = imfs_sum / num_ensembles
imfs_mean20[2] = imfs_mean20[2] - np.mean(imfs_mean20[2])
imfs_mean20[3] = imfs_mean20[3] - np.mean(imfs_mean20[3])
imfs_mean20[4] = imfs_mean20[4] - np.mean(imfs_mean20[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Piraievs", y=0.83)
for n, imf in enumerate(imfs_mean20):
    plt.subplot(len(imfs_mean20)+1, 1, n+2)
    plt.plot(pir_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean20)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean20)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_piraievs.npy', imfs_mean20)
#np.save('imfs_piraievs_nogrd.npy', imfs_mean20)
imfs_piraievs = np.load('path/imfs_piraievs.npy')
imfs_piraievs_nogrd = np.load('path/imfs_piraievs_nogrd.npy')


# SIROS -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
sir=pd.read_csv('path/siros.txt',\
                 sep=';',header=None)[:]
datesir = pd.date_range('1/1/1969','12/31/2022', freq='M')
sir.index = datesir
sir = sir[1]
sir = sir.replace(-99999, np.nan)
valid_counts_per_year = sir.groupby(sir.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    sir[sir.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,9,29]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = sir - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,17,64]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = sir - (alpha * era5_anomaly)
sir = ib_0.combine_first(ib_1)
# --
sir_y = sir.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
sir_y = interpolate_short_gaps(sir_y.copy())
# GIA
trend = 0.09
time_passed = np.arange(sir_y.shape[0])[:]
cumulative_trend = time_passed * trend
sir_y = sir_y - cumulative_trend
sir_y2 = sir_y.dropna()
# GRD
grd = sea_barystatic[:,254,409]
grd = pd.Series(grd, index=datebary)
sir_y = sir_y - grd
sir_y = sir_y.dropna()

sea = sir_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean21 = imfs_sum / num_ensembles
imfs_mean21[2] = imfs_mean21[2] - np.mean(imfs_mean21[2])
imfs_mean21[3] = imfs_mean21[3] - np.mean(imfs_mean21[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Siros", y=0.83)
for n, imf in enumerate(imfs_mean21):
    plt.subplot(len(imfs_mean21)+1, 1, n+2)
    plt.plot(sir_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean21)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean21)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_siros.npy', imfs_mean21)
#np.save('imfs_siros_nogrd.npy', imfs_mean21)
imfs_siros = np.load('path/imfs_siros.npy')
imfs_siros_nogrd = np.load('path/imfs_siros_nogrd.npy')


# BODRUM -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
bod=pd.read_csv('path/bodrum.txt',\
                 sep=';',header=None)[:]
datebod = pd.date_range('12/1/1985','9/30/2009', freq='M')
bod.index = datebod
bod = bod[1]
bod = bod.replace(-99999, np.nan)
valid_counts_per_year = bod.groupby(bod.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    bod[bod.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,9,31]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = bod - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,18,69]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = bod - (alpha * era5_anomaly)
bod = ib_0.combine_first(ib_1)
# --
bod_y = bod.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
bod_y = interpolate_short_gaps(bod_y.copy())
# GIA
trend = -0.01
time_passed = np.arange(bod_y.shape[0])[:]
cumulative_trend = time_passed * trend
bod_y = bod_y - cumulative_trend
# GRD
grd = sea_barystatic[:,254,414]
grd = pd.Series(grd, index=datebary)
bod_y = bod_y - grd
bod_y = bod_y.dropna()

sea = bod_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean28 = imfs_sum / num_ensembles
imfs_mean28[1] = imfs_mean28[1] - np.mean(imfs_mean28[1])
imfs_mean28[2] = imfs_mean28[2] - np.mean(imfs_mean28[2])
imfs_mean28[3] = imfs_mean28[3] - np.mean(imfs_mean28[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Bodrum", y=0.83)
for n, imf in enumerate(imfs_mean28):
    plt.subplot(len(imfs_mean28)+1, 1, n+2)
    plt.plot(bod_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean28)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean28)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_bodrum.npy', imfs_mean28)
#np.save('imfs_bodrum_nogrd.npy', imfs_mean28)
imfs_bodrum = np.load('path/imfs_bodrum.npy')
imfs_bodrum_nogrd = np.load('path/imfs_bodrum_nogrd.npy')


# IZMIR -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
izm=pd.read_csv('path/izmir.txt',\
                 sep=';',header=None)[:]
dateizm = pd.date_range('12/1/1985','12/31/2009', freq='M')
izm.index = dateizm
izm = izm[1]
izm = izm.replace(-99999, np.nan)
valid_counts_per_year = izm.groupby(izm.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    izm[izm.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,8,31]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = izm - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,15,67]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = izm - (alpha * era5_anomaly)
izm = ib_0.combine_first(ib_1)
# --
izm_y = izm.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
izm_y = interpolate_short_gaps(izm_y.copy())
# GIA
trend = -0.14
time_passed = np.arange(izm_y.shape[0])[:]
cumulative_trend = time_passed * trend
izm_y = izm_y - cumulative_trend
# GRD
grd = sea_barystatic[:,256,413]
grd = pd.Series(grd, index=datebary)
izm_y = izm_y - grd
izm_y = izm_y.dropna()

sea = izm_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean29 = imfs_sum / num_ensembles
imfs_mean29[1] = imfs_mean29[1] - np.mean(imfs_mean29[1])
imfs_mean29[2] = imfs_mean29[2] - np.mean(imfs_mean29[2])
imfs_mean29[3] = imfs_mean29[3] - np.mean(imfs_mean29[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Izmir", y=0.83)
for n, imf in enumerate(imfs_mean29):
    plt.subplot(len(imfs_mean29)+1, 1, n+2)
    plt.plot(izm_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean29)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean29)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_izmir.npy', imfs_mean29)
#np.save('imfs_izmir_nogrd.npy', imfs_mean29)
imfs_izmir = np.load('path/imfs_izmir.npy')
imfs_izmir_nogrd = np.load('path/imfs_izmir_nogrd.npy')


# - - - - - - - - - - - - - - - - -  --  -
series4 = [(ler_y.index[:], ((imfs_leros[1])[:])/10, 'black', 'Leros'),
          (khi_y.index[:], ((imfs_khios[1])[:])/10, 'green', 'Khios'),
          (alex_y.index[:], ((imfs_alexandroupolis[1])[:])/10, 'red', 'Alexandroupolis'),
          (the_y.index[:], ((imfs_thessaloniki[1])[:])/10, 'blue', 'Thessaloniki'),
          (kha_y.index[:], ((imfs_khalkis[1])[:])/10, 'orange', 'Khalkis'),
          (pir_y.index[:], ((imfs_piraievs[1])[:])/10, 'cyan', 'Piraievs'),
          (sir_y.index[:], ((imfs_siros[1])[:])/10, 'purple', 'Siros'),
          (bod_y.index[:], ((imfs_bodrum[1])[:])/10, 'magenta', 'Bodrum'),
          (izm_y.index[:], ((imfs_izmir[1])[:])/10, 'gold', 'Izmir')
          ]

plt.figure(figsize=(26,8), dpi=300)
for serie in series4:
    idx, data, color, label = serie
    idx = idx - pd.DateOffset(months=11)
    plt.plot(idx, data, label=label, color=color, linewidth=2)
    maxima = argrelextrema(data, np.greater)
    minima = argrelextrema(data, np.less)
    for max_idx in maxima[0]:
        plt.axvspan(idx[max_idx] - timedelta(365.25/2), idx[max_idx] + timedelta(365.25/2), color='r', alpha=0.1)
    for min_idx in minima[0]:
        plt.axvspan(idx[min_idx] - timedelta(365.25/2), idx[min_idx] + timedelta(365.25/2), color='b', alpha=0.1)
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))  
plt.gca().xaxis.set_minor_locator(mdates.YearLocator()) 
plt.xlabel('time', fontsize=16)
plt.ylabel('sea level (cm)', fontsize=16)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
date_bande = ['1991.5', '1997.5', '2006.5', '2011.5', '2017.5']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(egeo_basin.index, egeo_basin*100, linestyle='--', linewidth=3, label='Ionian mean from SA')  # Convertito da m a cm
plt.legend(handlelength=1, fontsize=16, framealpha=1, loc='upper right', ncol=9, facecolor='white')
plt.show()

dfs = [pd.DataFrame(data, index=idx) for idx, data, _, _ in series4]
aligned_dfs = pd.concat(dfs, axis=1)
mean_series = aligned_dfs.mean(axis=1)
mean_series = mean_series.shift(freq='-11M')
max_series = aligned_dfs.max(axis=1)
min_series = aligned_dfs.min(axis=1)

plt.figure(figsize=(17,5), dpi=300)
maxima_mean = argrelextrema(mean_series.values, np.greater)[0]
minima_mean = argrelextrema(mean_series.values, np.less)[0]
index_2002 = mean_series[mean_series.index.year == 2002].index
index_2001 = mean_series[mean_series.index.year == 2001].index
index_to_remove = list(index_2002) + list(index_2001)
maxima_mean = [idx for idx in maxima_mean if mean_series.index[idx] not in index_to_remove]
minima_mean = [idx for idx in minima_mean if mean_series.index[idx] not in index_to_remove]
combined = sorted(list(maxima_mean) + list(minima_mean))
combined = [0] + combined + [len(mean_series)-1]
colors = ["#56B4E9","#E69F00",]
for i in range(len(combined)-1):
    start_idx = combined[i]
    end_idx = combined[i+1]
    plt.axvspan(mean_series.index[start_idx], mean_series.index[end_idx], color=colors[i % 2], alpha=0.3)
for max_idx in maxima_mean:
    plt.axvspan(mean_series.index[max_idx] - timedelta(365.25/2),
                mean_series.index[max_idx] + timedelta(365.25/2),
                color='white', alpha=1)
for min_idx in minima_mean:
    plt.axvspan(mean_series.index[min_idx] - timedelta(365.25/2),
                mean_series.index[min_idx] + timedelta(365.25/2),
                color='white', alpha=1)
std_dev_series = aligned_dfs.std(axis=1)
std_dev_series = std_dev_series.shift(freq='-11M')
plt.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4)
plt.plot(mean_series.index, mean_series, color='black', label = r'TG ensemble mean $\pm 1\sigma$', linewidth=2)
start_year = datetime(1969, 1, 1)
end_year = datetime(2018, 1, 31)
plt.gca().set_xlim([start_year, end_year])
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))
plt.gca().xaxis.set_minor_locator(mdates.YearLocator(1))
plt.xlabel('time', fontsize=20)
plt.ylabel('sea level (cm)', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
date_bande = ['1993', '1999', '2007', '2011', '2017']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(egeo_basin.index, egeo_basin*100, linestyle='--', linewidth=3, label='SA basin mean', color='red')
plt.title('Aegean', fontsize=20)
plt.legend(handlelength=1.5, fontsize=20, framealpha=1, loc='upper center', ncol=9, facecolor='white')
plt.show()

print("Maxima dates:")
for idx in maxima_mean:
    print(mean_series.index[idx].date())
print("\nMinima dates:")
for idx in minima_mean:
    print(mean_series.index[idx].date())

series4_nogrd = [(ler_y2.index[:], ((imfs_leros_nogrd[1])[:])/10, 'black', 'Leros'),
          (khi_y.index[:], ((imfs_khios_nogrd[1])[:])/10, 'green', 'Khios'),
          (alex_y2.index[:], ((imfs_alexandroupolis_nogrd[1])[:])/10, 'red', 'Alexandroupolis'),
          (the_y.index[:], ((imfs_thessaloniki_nogrd[1])[:])/10, 'blue', 'Thessaloniki'),
          (kha_y2.index[:], ((imfs_khalkis_nogrd[1])[:])/10, 'orange', 'Khalkis'),
          (pir_y2.index[:], ((imfs_piraievs_nogrd[1])[:])/10, 'cyan', 'Piraievs'),
          (sir_y2.index[:], ((imfs_siros_nogrd[1])[:])/10, 'purple', 'Siros'),
          (bod_y.index[:], ((imfs_bodrum_nogrd[1])[:])/10, 'magenta', 'Bodrum'),
          (izm_y.index[:], ((imfs_izmir_nogrd[1])[:])/10, 'gold', 'Izmir')
          ]


# - - - - - - -    TYRRHENIAN


# PALERMO -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
pal=pd.read_csv('path/palermo.txt',\
                 sep=';',header=None)[:]
datepal = pd.date_range('6/1/1896','6/30/1922', freq='M')
pal.index = datepal
pal = pal[1]
pal = pal.replace(-99999, np.nan)
valid_counts_per_year = pal.groupby(pal.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    pal[pal.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,8,19]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = pal - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,16,41]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = pal - (alpha * era5_anomaly)
pal = ib_0.combine_first(ib_1)
# --
pal_y = pal.resample('Y').mean()
# GIA
trend = -0.49
time_passed = np.arange(pal_y.shape[0])[:]
cumulative_trend = time_passed * trend
pal_y = pal_y - cumulative_trend
# GRD
grd = sea_barystatic[:,256,386]
grd = pd.Series(grd, index=datebary)
pal_y = pal_y - grd
pal_y = pal_y.dropna()

sea = pal_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean30 = imfs_sum / num_ensembles
imfs_mean30[1] = imfs_mean30[1] - np.mean(imfs_mean30[1])
imfs_mean30[2] = imfs_mean30[2] - np.mean(imfs_mean30[2])
imfs_mean30[3] = imfs_mean30[3] - np.mean(imfs_mean30[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Palermo", y=0.83)
for n, imf in enumerate(imfs_mean30):
    plt.subplot(len(imfs_mean30)+1, 1, n+2)
    plt.plot(pal_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean30)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean30)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_palermo.npy', imfs_mean30)
#np.save('imfs_palermo_nogrd.npy', imfs_mean30)
imfs_palermo = np.load('path/imfs_palermo.npy')
imfs_palermo_nogrd = np.load('path/imfs_palermo_nogrd.npy')


# NAPOLI (MANDRACCHIO) -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
nap=pd.read_csv('path/napoli.txt',\
                 sep=';',header=None)[:]
datenap = pd.date_range('6/1/1896','6/30/1922', freq='M')
nap.index = datenap
nap = nap[1]
nap = nap.replace(-99999, np.nan)
valid_counts_per_year = nap.groupby(nap.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    nap[nap.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,6,20]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = nap - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,10,42]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = nap - (alpha * era5_anomaly)
nap = ib_0.combine_first(ib_1)
# --
nap_y = nap.resample('Y').mean()
# GIA
trend = 0.06
time_passed = np.arange(nap_y.shape[0])[:]
cumulative_trend = time_passed * trend
nap_y = nap_y - cumulative_trend
# GRD
grd = sea_barystatic[:,261,388]
grd = pd.Series(grd, index=datebary)
nap_y = nap_y - grd
nap_y = nap_y.dropna()

sea = nap_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean31 = imfs_sum / num_ensembles
imfs_mean31[1] = imfs_mean31[1] - np.mean(imfs_mean31[1])
imfs_mean31[2] = imfs_mean31[2] - np.mean(imfs_mean31[2])
imfs_mean31[3] = imfs_mean31[3] - np.mean(imfs_mean31[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Napoli", y=0.83)
for n, imf in enumerate(imfs_mean31):
    plt.subplot(len(imfs_mean31)+1, 1, n+2)
    plt.plot(nap_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean31)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean31)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_napoli.npy', imfs_mean31)
#np.save('imfs_napoli_nogrd.npy', imfs_mean31)
imfs_napoli = np.load('path/imfs_napoli.npy')
imfs_napoli_nogrd = np.load('path/imfs_napoli_nogrd.npy')


# CIVITAVECCHIA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
civ=pd.read_csv('path/civitavecchia.txt',\
                 sep=';',header=None)[:]
dateciv = pd.date_range('7/1/1896','6/30/1922', freq='M')
civ.index = dateciv
civ.loc[civ[3] == 1, 1] = np.nan
civ = civ[1]
civ = civ.replace(-99999, np.nan)
valid_counts_per_year = civ.groupby(civ.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    civ[civ.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,5,17]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = civ - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,8,38]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = civ - (alpha * era5_anomaly)
civ = ib_0.combine_first(ib_1)
# --
civ_y = civ.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
civ_y = interpolate_short_gaps(civ_y.copy())
# GIA
trend = 0.07
time_passed = np.arange(civ_y.shape[0])[:]
cumulative_trend = time_passed * trend
civ_y = civ_y - cumulative_trend
# GRD
grd = sea_barystatic[:,264,383]
grd = pd.Series(grd, index=datebary)
civ_y = civ_y - grd
civ_y = civ_y.dropna()

sea = civ_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean32 = imfs_sum / num_ensembles
imfs_mean32[1] = imfs_mean32[1] - np.mean(imfs_mean32[1])
imfs_mean32[2] = imfs_mean32[2] - np.mean(imfs_mean32[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Civitavecchia", y=0.83)
for n, imf in enumerate(imfs_mean32):
    plt.subplot(len(imfs_mean32)+1, 1, n+2)
    plt.plot(civ_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean32)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean32)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_civitavecchia.npy', imfs_mean32)
#np.save('imfs_civitavecchia_nogrd.npy', imfs_mean32)
imfs_civitavecchia = np.load('path/imfs_civitavecchia.npy')
imfs_civitavecchia_nogrd = np.load('path/imfs_civitavecchia_nogrd.npy')


# CAGLIARI -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
cag=pd.read_csv('path/cagliari.txt',\
                 sep=';',header=None)[:]
datecag = pd.date_range('8/1/1896','12/31/1934', freq='M')
cag.index = datecag
cag = cag[1]
cag = cag.replace(-99999, np.nan)
valid_counts_per_year = cag.groupby(cag.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    cag[cag.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,7,15]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = cag - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,14,32]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = cag - (alpha * era5_anomaly)
cag = ib_0.combine_first(ib_1)
# --
cag_y = cag.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
cag_y = interpolate_short_gaps(cag_y.copy())
# GIA
trend = 0.25
time_passed = np.arange(cag_y.shape[0])[:]
cumulative_trend = time_passed * trend
cag_y = cag_y - cumulative_trend
# GRD
grd = sea_barystatic[:,258,378]
grd = pd.Series(grd, index=datebary)
cag_y = cag_y - grd
cag_y = cag_y.dropna()

sea = cag_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean33 = imfs_sum / num_ensembles
imfs_mean33[3] = imfs_mean33[3] - np.mean(imfs_mean33[3])
imfs_mean33[2] = imfs_mean33[2] - np.mean(imfs_mean33[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Cagliari", y=0.83)
for n, imf in enumerate(imfs_mean33):
    plt.subplot(len(imfs_mean33)+1, 1, n+2)
    plt.plot(cag_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean33)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean33)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_cagliari.npy', imfs_mean33)
#np.save('imfs_cagliari_nogrd.npy', imfs_mean33)
imfs_cagliari = np.load('path/imfs_cagliari.npy')
imfs_cagliari_nogrd = np.load('path/imfs_cagliari_nogrd.npy')


# GENOVA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
# data from 2001 and 2014 were merged from Genova II
gen1=pd.read_csv('path/genova.txt',\
                 sep=';',header=None)[:]
dategen1 = pd.date_range('1/1/1884','12/31/2021', freq='M')
gen1.index = dategen1
gen1.loc[gen1[3] == 1, 1] = np.nan
gen1 = gen1[1]
gen1 = gen1.replace(-99999, np.nan)
valid_counts_per_year = gen1.groupby(gen1.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    gen1[gen1.index.year == year] = np.nan
gen2=pd.read_csv('path/genova2.txt',\
                 sep=';',header=None)[:]
dategen2 = pd.date_range('1/1/2001','12/31/2014', freq='M')
gen2.index = dategen2
gen2 = gen2[1]
gen2 = gen2.replace(-99999, np.nan)
valid_counts_per_year = gen2.groupby(gen2.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    gen2[gen2.index.year == year] = np.nan
gen2 = gen2+80
gen1_aligned, gen2_aligned = gen1.align(gen2, join='outer')
gen = pd.Series(np.where(np.isnan(gen1_aligned), gen2_aligned, 
                                    np.where(np.isnan(gen2_aligned), gen1_aligned, 
                                             (gen1_aligned + gen2_aligned) / 2)), index=gen1_aligned.index)
# IB
era20c_hPa = pressure_era20c[:,3,15]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = gen - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,3,52]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = gen - (alpha * era5_anomaly)
gen = ib_0.combine_first(ib_1)
# --
gen_y = gen.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
gen_y = interpolate_short_gaps(gen_y.copy())
# GIA
trend = -0.07
time_passed = np.arange(gen_y.shape[0])[:]
cumulative_trend = time_passed * trend
gen_y = gen_y - cumulative_trend
gen_y2 = gen_y.dropna()
gen_y2 = gen_y2['1928':]
# GRD
grd = sea_barystatic[:,188,397]
grd = pd.Series(grd, index=datebary)
gen_y = gen_y - grd
gen_y = gen_y.dropna()
gen_y = gen_y['1928':]

sea = gen_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean34 = imfs_sum / num_ensembles
imfs_mean34[3] = imfs_mean34[3] - np.mean(imfs_mean34[3])
imfs_mean34[4] = imfs_mean34[4] - np.mean(imfs_mean34[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Genova", y=0.83)
for n, imf in enumerate(imfs_mean34):
    plt.subplot(len(imfs_mean34)+1, 1, n+2)
    plt.plot(gen_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean34)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean34)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_genova.npy', imfs_mean34)
#np.save('imfs_genova_nogrd.npy', imfs_mean34)
imfs_genova = np.load('path/imfs_genova.npy')
imfs_genova_nogrd = np.load('path/imfs_genova_nogrd.npy')

# - - - - - - - - - - - - - - - - -  --  -
series = [(pal_y.index[:], ((imfs_palermo[1])[:])/10, 'pink', 'Palermo'),
          (nap_y.index[:], ((imfs_napoli[1])[:])/10, 'cyan', 'Napoli'),
          (cag_y.index[:], ((imfs_cagliari[1])[:])/10, 'red', 'Cagliari'),
          (civ_y.index[:], ((imfs_civitavecchia[1])[:])/10, 'black', 'Civitavecchia'),
          (gen_y.index[:], ((imfs_genova[1])[:])/10, 'blue', 'Genova'),
          ]

plt.figure(figsize=(26,8), dpi=300)
for serie in series:
    idx, data, color, label = serie
    idx = idx - pd.DateOffset(months=11)
    plt.plot(idx, data, label=label, color=color, linewidth=2)
    maxima = argrelextrema(data, np.greater)
    minima = argrelextrema(data, np.less)
    for max_idx in maxima[0]:
        plt.axvspan(idx[max_idx] - timedelta(365.25/2), idx[max_idx] + timedelta(365.25/2), color='r', alpha=0.1)
    for min_idx in minima[0]:
        plt.axvspan(idx[min_idx] - timedelta(365.25/2), idx[min_idx] + timedelta(365.25/2), color='b', alpha=0.1)
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))  
plt.gca().xaxis.set_minor_locator(mdates.YearLocator()) 
plt.xlabel('time', fontsize=16)
plt.ylabel('sea level (cm)', fontsize=16)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
date_bande = ['1991.5', '1997.5', '2006.5', '2011.5', '2017.5']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(tyr_basin.index, tyr_basin*100, linestyle='--', linewidth=3, label='Ionian mean from SA')
plt.legend(handlelength=1, fontsize=16, framealpha=1, loc='upper right', ncol=9, facecolor='white')
plt.show()

dfs = [pd.DataFrame(data, index=idx) for idx, data, _, _ in series]
aligned_dfs = pd.concat(dfs, axis=1)
mean_series = aligned_dfs.mean(axis=1)
mean_series = mean_series.shift(freq='-11M')
max_series = aligned_dfs.max(axis=1)
min_series = aligned_dfs.min(axis=1)

plt.figure(figsize=(17,5), dpi=300)
maxima_mean = argrelextrema(mean_series.values, np.greater)[0]
minima_mean = argrelextrema(mean_series.values, np.less)[0]
combined = sorted(list(maxima_mean) + list(minima_mean))
combined = [0] + combined + [len(mean_series)-1]
colors = ["#56B4E9","#E69F00",]
for i in range(len(combined)-1):
    start_idx = combined[i]
    end_idx = combined[i+1]
    plt.axvspan(mean_series.index[start_idx], mean_series.index[end_idx], color=colors[i % 2], alpha=0.3)
for max_idx in maxima_mean:
    plt.axvspan(mean_series.index[max_idx] - timedelta(365.25/2),
                mean_series.index[max_idx] + timedelta(365.25/2),
                color='white', alpha=1)
for min_idx in minima_mean:
    plt.axvspan(mean_series.index[min_idx] - timedelta(365.25/2),
                mean_series.index[min_idx] + timedelta(365.25/2),
                color='white', alpha=1)
std_dev_series = aligned_dfs.std(axis=1)
std_dev_series = std_dev_series.shift(freq='-11M')
plt.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4)
plt.plot(mean_series.index, mean_series, color='black', label = r'TG ensemble mean $\pm 1\sigma$', linewidth=2)
start_year = datetime(1900, 1, 1)
end_year = datetime(2018, 1, 31)
plt.gca().set_xlim([start_year, end_year])
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))
plt.gca().xaxis.set_minor_locator(mdates.YearLocator(1))
plt.xlabel('time', fontsize=20)
plt.ylabel('sea level (cm)', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
date_bande = ['1991', '1996', '2006', '2010', '2017']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(tyr_basin.index, tyr_basin*100, linestyle='--', linewidth=3, label='SA basin mean', color='red')
plt.title('Tyrrhenian', fontsize=20)
plt.legend(handlelength=1.5, fontsize=20, framealpha=1, loc='upper center', ncol=9, facecolor='white')
plt.show()

print("Maxima dates:")
for idx in maxima_mean:
    print(mean_series.index[idx].date())
print("\nMinima dates:")
for idx in minima_mean:
    print(mean_series.index[idx].date())




# WESTERN BASIN - - - - - - - -------------------------------------------------
# -----------------------------------------------------------------------------


# PORTO MAURIZIO -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
mau=pd.read_csv('path/porto maurizio.txt',\
                 sep=';',header=None)[:]
datemau = pd.date_range('8/1/1896','7/31/1922', freq='M')
mau.index = datemau
mau = mau[1]
mau = mau.replace(-99999, np.nan)
valid_counts_per_year = mau.groupby(mau.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    mau[mau.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,4,14]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = mau - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,4,30]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = mau - (alpha * era5_anomaly)
mau = ib_0.combine_first(ib_1)
# --
mau_y = mau.resample('Y').mean()
# GIA
trend = 0.03
time_passed = np.arange(mau_y.shape[0])[:]
cumulative_trend = time_passed * trend
mau_y = mau_y - cumulative_trend
# GRD
grd = sea_barystatic[:,266,376]
grd = pd.Series(grd, index=datebary)
mau_y = mau_y - grd
mau_y = mau_y.dropna()

sea = mau_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean35 = imfs_sum / num_ensembles
imfs_mean35[1] = imfs_mean35[1] - np.mean(imfs_mean35[1])
imfs_mean35[2] = imfs_mean35[2] - np.mean(imfs_mean35[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Porto Maurizio", y=0.83)
for n, imf in enumerate(imfs_mean35):
    plt.subplot(len(imfs_mean35)+1, 1, n+2)
    plt.plot(mau_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean35)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean35)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_porto_maurizio.npy', imfs_mean35)
#np.save('imfs_porto_maurizio_nogrd.npy', imfs_mean35)
imfs_portomaurizio = np.load('path/imfs_porto_maurizio.npy')
imfs_portomaurizio_nogrd = np.load('path/imfs_porto_maurizio_nogrd.npy')


# TOULON -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
tou=pd.read_csv('path/toulon.txt',\
                 sep=';',header=None)[:]
datetou = pd.date_range('1/1/1961','3/31/2022', freq='M')
tou.index = datetou
tou = tou[1]
tou = tou.replace(-99999, np.nan)
valid_counts_per_year = tou.groupby(tou.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    tou[tou.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,4,12]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = tou - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,6,26]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = tou - (alpha * era5_anomaly)
tou = ib_0.combine_first(ib_1)
# --
tou_y = tou.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
tou_y = interpolate_short_gaps(tou_y.copy())
# GIA
trend = 0.12
time_passed = np.arange(tou_y.shape[0])[:]
cumulative_trend = time_passed * trend
tou_y = tou_y - cumulative_trend
tou_y2 = tou_y.dropna()
tou_y2 = tou_y2['1993':]
# GRD
grd = sea_barystatic[:,266,371]
grd = pd.Series(grd, index=datebary)
tou_y = tou_y - grd
tou_y = tou_y.dropna()
tou_y = tou_y['1993':]

sea = tou_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean36 = imfs_sum / num_ensembles
imfs_mean36[1] = imfs_mean36[1] - np.mean(imfs_mean36[1])
imfs_mean36[2] = imfs_mean36[2] - np.mean(imfs_mean36[2])
imfs_mean36[3] = imfs_mean36[3] - np.mean(imfs_mean36[3])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Toulon", y=0.83)
for n, imf in enumerate(imfs_mean36):
    plt.subplot(len(imfs_mean36)+1, 1, n+2)
    plt.plot(tou_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean36)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean36)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_toulon.npy', imfs_mean36)
#np.save('imfs_toulon_nogrd.npy', imfs_mean36)
imfs_toulon = np.load('path/imfs_toulon.npy')
imfs_toulon_nogrd = np.load('path/imfs_toulon_nogrd.npy')


# MARSEILLE -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
mar=pd.read_csv('path/marseille.txt',\
                 sep=';',header=None)[:]
datemar = pd.date_range('2/1/1885','3/31/2022', freq='M')
mar.index = datemar
mar.loc[mar[3] == 1, 1] = np.nan
mar = mar[1]
mar = mar.replace(-99999, np.nan)
valid_counts_per_year = mar.groupby(mar.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    mar[mar.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,4,12]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = mar - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,5,25]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = mar - (alpha * era5_anomaly)
mar = ib_0.combine_first(ib_1)
# --
mar_y = mar.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
mar_y = interpolate_short_gaps(mar_y.copy())
# GIA
trend = 0.06
time_passed = np.arange(mar_y.shape[0])[:]
cumulative_trend = time_passed * trend
mar_y = mar_y - cumulative_trend
mar_y2 = mar_y.dropna()
# GRD
grd = sea_barystatic[:,266,370]
grd = pd.Series(grd, index=datebary)
mar_y = mar_y - grd
mar_y = mar_y.dropna()

sea = mar_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean37 = imfs_sum / num_ensembles
imfs_mean37[3] = imfs_mean37[3] - np.mean(imfs_mean37[3])
imfs_mean37[4] = imfs_mean37[4] - np.mean(imfs_mean37[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Marseille", y=0.83)
for n, imf in enumerate(imfs_mean37):
    plt.subplot(len(imfs_mean37)+1, 1, n+2)
    plt.plot(mar_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean37)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean37)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_marseille.npy', imfs_mean37)
#np.save('imfs_marseille_nogrd.npy', imfs_mean37)
imfs_marseille = np.load('path/imfs_marseille.npy')
imfs_marseille_nogrd = np.load('path/imfs_marseille_nogrd.npy')


# SETE -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
sete=pd.read_csv('path/sete.txt',\
                 sep=';',header=None)[:]
datesete = pd.date_range('1/1/1992','6/30/2022', freq='M')
sete.index = datesete
sete = sete[1]
sete = sete.replace(-99999, np.nan)
valid_counts_per_year = sete.groupby(sete.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    sete[sete.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,4,10]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = sete - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,5,21]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = sete - (alpha * era5_anomaly)
sete = ib_0.combine_first(ib_1)
# --
sete_y = sete.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
sete_y = interpolate_short_gaps(sete_y.copy())
# GIA
trend = -0.07
time_passed = np.arange(sete_y.shape[0])[:]
cumulative_trend = time_passed * trend
sete_y = sete_y - cumulative_trend
sete_y2 = sete_y.dropna()
# GRD
grd = sea_barystatic[:,266,367]
grd = pd.Series(grd, index=datebary)
sete_y = sete_y - grd
sete_y = sete_y.dropna()

sea = sete_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean38 = imfs_sum / num_ensembles
imfs_mean38[3] = imfs_mean38[3] - np.mean(imfs_mean38[3])
imfs_mean38[2] = imfs_mean38[2] - np.mean(imfs_mean38[2])
imfs_mean38[1] = imfs_mean38[1] - np.mean(imfs_mean38[1])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Sete", y=0.83)
for n, imf in enumerate(imfs_mean38):
    plt.subplot(len(imfs_mean38)+1, 1, n+2)
    plt.plot(sete_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean38)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean38)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_sete.npy', imfs_mean38)
#np.save('imfs_sete_nogrd.npy', imfs_mean38)
imfs_sete = np.load('path/imfs_sete.npy')
imfs_sete_nogrd = np.load('path/imfs_sete_nogrd.npy')


# L'ESTARTIT -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
est=pd.read_csv('path/estartit.txt',\
                 sep=';',header=None)[:]
dateest = pd.date_range('1/1/1990','12/31/2022', freq='M')
est.index = dateest
est = est[1]
# IB
era20c_hPa = pressure_era20c[:,5,10]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = est - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,8,20]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = est - (alpha * era5_anomaly)
est = ib_0.combine_first(ib_1)
# --
est_y = est.resample('Y').mean()
# GIA
trend = 0.1
time_passed = np.arange(est_y.shape[0])[:]
cumulative_trend = time_passed * trend
est_y = est_y - cumulative_trend
est_y2 = est_y.dropna()
# GRD
grd = sea_barystatic[:,264,366]
grd = pd.Series(grd, index=datebary)
est_y = est_y - grd
est_y = est_y.dropna()

sea = est_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean39 = imfs_sum / num_ensembles
imfs_mean39[3] = imfs_mean39[3] - np.mean(imfs_mean39[3])
imfs_mean39[2] = imfs_mean39[2] - np.mean(imfs_mean39[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("L'Estartit", y=0.83)
for n, imf in enumerate(imfs_mean39):
    plt.subplot(len(imfs_mean39)+1, 1, n+2)
    plt.plot(est_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean39)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean39)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_estartit.npy', imfs_mean39)
#np.save('imfs_estartit_nogrd.npy', imfs_mean39)
imfs_estartit = np.load('path/imfs_estartit.npy')
imfs_estartit_nogrd = np.load('path/imfs_estartit_nogrd.npy')


# BARCELONA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
barc=pd.read_csv('path/barcelona.txt',\
                 sep=';',header=None)[:]
datebarc = pd.date_range('1/1/1993','12/31/2022', freq='M')
barc.index = datebarc
barc = barc[1]
barc = barc.replace(-99999, np.nan)
valid_counts_per_year = barc.groupby(barc.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    barc[barc.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,6,9]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = barc - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,9,18]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = barc - (alpha * era5_anomaly)
barc = ib_0.combine_first(ib_1)
# --
barc_y = barc.resample('Y').mean()
# GIA
trend = 0.07
time_passed = np.arange(barc_y.shape[0])[:]
cumulative_trend = time_passed * trend
barc_y = barc_y - cumulative_trend
barc_y2 = barc_y.dropna()
# GRD
grd = sea_barystatic[:,262,364]
grd = pd.Series(grd, index=datebary)
barc_y = barc_y - grd
barc_y = barc_y.dropna()

sea = barc_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean40 = imfs_sum / num_ensembles
imfs_mean40[3] = imfs_mean40[3] - np.mean(imfs_mean40[3])
imfs_mean40[2] = imfs_mean40[2] - np.mean(imfs_mean40[2])
imfs_mean40[1] = imfs_mean40[1] - np.mean(imfs_mean40[1])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Barcelona", y=0.83)
for n, imf in enumerate(imfs_mean40):
    plt.subplot(len(imfs_mean40)+1, 1, n+2)
    plt.plot(barc_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean40)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean40)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_barcelona.npy', imfs_mean40)
#np.save('imfs_barcelona_nogrd.npy', imfs_mean40)
imfs_barcelona = np.load('path/imfs_barcelona.npy')
imfs_barcelona_nogrd = np.load('path/imfs_barcelona_nogrd.npy')


# VALENCIA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
vale=pd.read_csv('path/valencia.txt',\
                 sep=';',header=None)[:]
datevale = pd.date_range('1/1/1994','12/31/2022', freq='M')
vale.index = datevale
vale = vale[1]
vale = vale.replace(-99999, np.nan)
valid_counts_per_year = vale.groupby(vale.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    vale[vale.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,7,7]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = vale - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,13,13]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = vale - (alpha * era5_anomaly)
vale = ib_0.combine_first(ib_1)
# --
vale_y = vale.resample('Y').mean()
# GIA
trend = -0.05
time_passed = np.arange(vale_y.shape[0])[:]
cumulative_trend = time_passed * trend
vale_y = vale_y - cumulative_trend
vale_y2 = vale_y.dropna()
# GRD
grd = sea_barystatic[:,258,359]
grd = pd.Series(grd, index=datebary)
vale_y = vale_y - grd
vale_y = vale_y.dropna()

sea = vale_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean41 = imfs_sum / num_ensembles
imfs_mean41[3] = imfs_mean41[3] - np.mean(imfs_mean41[3])
imfs_mean41[2] = imfs_mean41[2] - np.mean(imfs_mean41[2])
imfs_mean41[1] = imfs_mean41[1] - np.mean(imfs_mean41[1])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Valencia", y=0.83)
for n, imf in enumerate(imfs_mean41):
    plt.subplot(len(imfs_mean41)+1, 1, n+2)
    plt.plot(vale_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean41)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean41)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_valencia.npy', imfs_mean41)
#np.save('imfs_valencia_nogrd.npy', imfs_mean41)
imfs_valencia = np.load('path/imfs_valencia.npy')
imfs_valencia_nogrd = np.load('path/imfs_valencia_nogrd.npy')


# ALICANTE 2 -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
ali=pd.read_csv('path/alicante.txt',\
                 sep=';',header=None)[:]
dateali = pd.date_range('1/1/1960','12/31/2020', freq='M')
ali.index = dateali
ali = ali[1]
ali = ali.replace(-99999, np.nan)
valid_counts_per_year = ali.groupby(ali.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    ali[ali.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,8,7]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = ali - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,15,13]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = ali - (alpha * era5_anomaly)
ali = ib_0.combine_first(ib_1)
# --
ali_y = ali.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
ali_y = interpolate_short_gaps(ali_y.copy())
# GIA
trend = 0.03
time_passed = np.arange(ali_y.shape[0])[:]
cumulative_trend = time_passed * trend
ali_y = ali_y - cumulative_trend
ali_y2 = ali_y.dropna()
# GRD
grd = sea_barystatic[:,256,359]
grd = pd.Series(grd, index=datebary)
ali_y = ali_y - grd
ali_y = ali_y.dropna()

sea = ali_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean42 = imfs_sum / num_ensembles
imfs_mean42[3] = imfs_mean42[3] - np.mean(imfs_mean42[3])
imfs_mean42[2] = imfs_mean42[2] - np.mean(imfs_mean42[2])
imfs_mean42[4] = imfs_mean42[4] - np.mean(imfs_mean42[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Alicante", y=0.83)
for n, imf in enumerate(imfs_mean42):
    plt.subplot(len(imfs_mean42)+1, 1, n+2)
    plt.plot(ali_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean42)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean42)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_alicante.npy', imfs_mean42)
#np.save('imfs_alicante_nogrd.npy', imfs_mean42)
imfs_alicante = np.load('path/imfs_alicante.npy')
imfs_alicante_nogrd = np.load('path/imfs_alicante_nogrd.npy')


# MALAGA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
mal1=pd.read_csv('path/malaga.txt',\
                 sep=';',header=None)[:]
datemal1 = pd.date_range('1/1/1944','12/31/2013', freq='M')
mal1.index = datemal1
mal1 = mal1[1]
mal1 = mal1.replace(-99999, np.nan)
mal2=pd.read_csv('path/malaga II.txt',\
                 sep=';',header=None)[:]
datemal2 = pd.date_range('7/1/1992','12/31/2022', freq='M')
mal2.index = datemal2
mal2 = mal2[1]
mal2 = mal2.replace(-99999, np.nan)
mal = pd.concat([mal1[:'2012'], (mal2['2013':]-76.94)])
valid_counts_per_year = mal.groupby(mal.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    mal[mal.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,10,3]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = mal - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,19,5]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = mal - (alpha * era5_anomaly)
mal = ib_0.combine_first(ib_1)
# --
mal_y = mal.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
mal_y = interpolate_short_gaps(mal_y.copy())
# GIA
trend = -0.13
time_passed = np.arange(mal_y.shape[0])[:]
cumulative_trend = time_passed * trend
mal_y = mal_y - cumulative_trend
mal_y2 = mal_y.dropna()
mal_y2 = mal_y2['1962':]
# GRD
grd = sea_barystatic[:,253,351]
grd = pd.Series(grd, index=datebary)
mal_y = mal_y - grd
mal_y = mal_y.dropna()
mal_y = mal_y['1962':]

sea = mal_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean43 = imfs_sum / num_ensembles
imfs_mean43[3] = imfs_mean43[3] - np.mean(imfs_mean43[3])
imfs_mean43[4] = imfs_mean43[4] - np.mean(imfs_mean43[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Malaga", y=0.83)
for n, imf in enumerate(imfs_mean43):
    plt.subplot(len(imfs_mean43)+1, 1, n+2)
    plt.plot(mal_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean43)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean43)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_malaga.npy', imfs_mean43)
#np.save('imfs_malaga_nogrd.npy', imfs_mean43)
imfs_malaga = np.load('path/imfs_malaga.npy')
imfs_malaga_nogrd = np.load('path/imfs_malaga_nogrd.npy')


# GIBRALTAR -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
gib=pd.read_csv('path/gibraltar.txt',\
                 sep=';',header=None)[:]
dategib = pd.date_range('7/1/1961','5/31/2014', freq='M')
gib.index = dategib
gib = gib[1]
gib = gib.replace(-99999, np.nan)
valid_counts_per_year = gib.groupby(gib.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    gib[gib.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,10,2]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = gib - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,20,4]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = gib - (alpha * era5_anomaly)
gib = ib_0.combine_first(ib_1)
# --
gib_y = gib.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
gib_y = interpolate_short_gaps(gib_y.copy())
# GIA
trend = -0.10
time_passed = np.arange(gib_y.shape[0])[:]
cumulative_trend = time_passed * trend
gib_y = gib_y - cumulative_trend
# GRD
grd = sea_barystatic[:,252,349]
grd = pd.Series(grd, index=datebary)
gib_y = gib_y - grd
gib_y = gib_y.dropna()
gib_y = gib_y['1962':'1982']

sea = gib_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean44 = imfs_sum / num_ensembles
imfs_mean44[1] = imfs_mean44[1] - np.mean(imfs_mean44[1])
imfs_mean44[2] = imfs_mean44[2] - np.mean(imfs_mean44[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Gibraltar", y=0.83)
for n, imf in enumerate(imfs_mean44):
    plt.subplot(len(imfs_mean44)+1, 1, n+2)
    plt.plot(gib_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean44)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean44)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_gibraltar.npy', imfs_mean44)
#np.save('imfs_gibraltar_nogrd.npy', imfs_mean44)
imfs_gibraltar = np.load('path/imfs_gibraltar.npy')
imfs_gibraltar_nogrd = np.load('path/imfs_gibraltar_nogrd.npy')


# ALGECIRAS -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
alg=pd.read_csv('path/algeciras.txt',\
                 sep=';',header=None)[:]
datealg = pd.date_range('7/1/1943','9/30/2002', freq='M')
alg.index = datealg
alg = alg[1]
alg = alg.replace(-99999, np.nan)
valid_counts_per_year = alg.groupby(alg.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    alg[alg.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,10,2]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = alg - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,20,4]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = alg - (alpha * era5_anomaly)
alg = ib_0.combine_first(ib_1)
# --
alg_y = alg.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
alg_y = interpolate_short_gaps(alg_y.copy())
# GIA
trend = -0.09
time_passed = np.arange(alg_y.shape[0])[:]
cumulative_trend = time_passed * trend
alg_y = alg_y - cumulative_trend
#alg_y = alg_y['1962':'2001']
# GRD
grd = sea_barystatic[:,252,349]
grd = pd.Series(grd, index=datebary)
alg_y = alg_y - grd
alg_y = alg_y.dropna()
alg_y = alg_y['1962':]

sea = alg_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean45 = imfs_sum / num_ensembles
imfs_mean45[3] = imfs_mean45[3] - np.mean(imfs_mean45[3])
imfs_mean45[2] = imfs_mean45[2] - np.mean(imfs_mean45[2])
imfs_mean45[4] = imfs_mean45[4] - np.mean(imfs_mean45[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Algeciras", y=0.83)
for n, imf in enumerate(imfs_mean45):
    plt.subplot(len(imfs_mean45)+1, 1, n+2)
    plt.plot(alg_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean45)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean45)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_algeciras.npy', imfs_mean45)
#np.save('imfs_algeciras_nogrd.npy', imfs_mean45)
imfs_algeciras = np.load('path/imfs_algeciras.npy')
imfs_algeciras_nogrd = np.load('path/imfs_algeciras_nogrd.npy')


# TARIFA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
tar1=pd.read_csv('path/tarifa.txt',\
                 sep=';',header=None)[:]
datetar1 = pd.date_range('9/1/1943','12/31/2018', freq='M')
tar1.index = datetar1
tar1 = tar1[1]
tar1 = tar1.replace(-99999, np.nan)
tar2=pd.read_csv('path/tarifa II.txt',\
                 sep=';',header=None)[:]
datetar2 = pd.date_range('8/1/2009','12/31/2022', freq='M')
tar2.index = datetar2
tar2 = tar2[1]
tar2 = tar2.replace(-99999, np.nan)
tar2 = tar2+65.89
tar1_aligned, tar2_aligned = tar1.align(tar2, join='outer')
tar = pd.Series(np.where(np.isnan(tar1_aligned), tar2_aligned, 
                                    np.where(np.isnan(tar2_aligned), tar1_aligned, 
                                             (tar1_aligned + tar2_aligned) / 2)), index=tar1_aligned.index)
valid_counts_per_year = tar.groupby(tar.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    tar[tar.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,10,2]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = tar - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,20,3]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = tar - (alpha * era5_anomaly)
tar = ib_0.combine_first(ib_1)
# --
tar_y = tar.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
tar_y = interpolate_short_gaps(tar_y.copy())
# GIA
trend = -0.08
time_passed = np.arange(tar_y.shape[0])[:]
cumulative_trend = time_passed * trend
tar_y = tar_y - cumulative_trend
tar_y2 = tar_y.dropna()
# GRD
grd = sea_barystatic[:,220,348]
grd = pd.Series(grd, index=datebary)
tar_y = tar_y - grd
tar_y = tar_y.dropna()

sea = tar_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean46 = imfs_sum / num_ensembles
imfs_mean46[3] = imfs_mean46[3] - np.mean(imfs_mean46[3])
imfs_mean46[4] = imfs_mean46[4] - np.mean(imfs_mean46[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Tarifa", y=0.83)
for n, imf in enumerate(imfs_mean46):
    plt.subplot(len(imfs_mean46)+1, 1, n+2)
    plt.plot(tar_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean46)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean46)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_tarifa.npy', imfs_mean46)
#np.save('imfs_tarifa_nogrd.npy', imfs_mean46)
imfs_tarifa = np.load('path/imfs_tarifa.npy')
imfs_tarifa_nogrd = np.load('path/imfs_tarifa_nogrd.npy')


# CEUTA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
ceu=pd.read_csv('path/ceuta.txt',\
                 sep=';',header=None)[:]
dateceu = pd.date_range('3/1/1944','12/31/2018', freq='M')
ceu.index = dateceu
ceu = ceu[1]
ceu = ceu.replace(-99999, np.nan)
valid_counts_per_year = ceu.groupby(ceu.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    ceu[ceu.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,10,2]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = ceu - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,20,3]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = ceu - (alpha * era5_anomaly)
ceu = ib_0.combine_first(ib_1)
# --
ceu_y = ceu.resample('Y').mean()
def interpolate_short_gaps(series, max_gap_length=3):
    start_gap = None
    for i in range(len(series)):
        if pd.isna(series[i]) and start_gap is None:
            start_gap = i
        elif not pd.isna(series[i]) and start_gap is not None:
            end_gap = i
            gap_length = end_gap - start_gap
            if gap_length <= max_gap_length:
                series[start_gap:end_gap] = series[start_gap-1:end_gap+1].interpolate()[1:-1]
            start_gap = None
    return series
ceu_y = interpolate_short_gaps(ceu_y.copy())
# GIA
trend = -0.09
time_passed = np.arange(ceu_y.shape[0])[:]
cumulative_trend = time_passed * trend
ceu_y = ceu_y - cumulative_trend
# GRD
grd = sea_barystatic[:,251,349]
grd = pd.Series(grd, index=datebary)
ceu_y = ceu_y - grd
ceu_y = ceu_y.dropna()

sea = ceu_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean47 = imfs_sum / num_ensembles
imfs_mean47[3] = imfs_mean47[3] - np.mean(imfs_mean47[3])
imfs_mean47[4] = imfs_mean47[4] - np.mean(imfs_mean47[4])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Ceuta", y=0.83)
for n, imf in enumerate(imfs_mean47):
    plt.subplot(len(imfs_mean47)+1, 1, n+2)
    plt.plot(ceu_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean47)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean47)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_ceuta.npy', imfs_mean47)
#np.save('imfs_ceuta_nogrd.npy', imfs_mean47)
imfs_ceuta = np.load('path/imfs_ceuta.npy')
imfs_ceuta_nogrd = np.load('path/imfs_ceuta_nogrd.npy')


# PALMA DE MALLORCA -------------------------------------------------------------------
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------
palma1=pd.read_csv('path/palma de mallorca.txt',\
                 sep=';',header=None)[:]
datepalma1 = pd.date_range('4/1/1997','12/31/2018', freq='M')
palma1.index = datepalma1
palma1 = palma1[1]
palma1 = palma1.replace(-99999, np.nan)
palma2=pd.read_csv('path/palma de mallorca II.txt',\
                 sep=';',header=None)[:]
datepalma2 = pd.date_range('10/1/2009','12/31/2022', freq='M')
palma2.index = datepalma2
palma2 = palma2[1]
palma2 = palma2.replace(-99999, np.nan)
palma2 = palma2+130
palma1_aligned, palma2_aligned = palma1.align(palma2, join='outer')
palma = pd.Series(np.where(np.isnan(palma1_aligned), palma2_aligned, 
                                    np.where(np.isnan(palma2_aligned), palma1_aligned, 
                                             (palma1_aligned + palma2_aligned) / 2)), index=palma1_aligned.index)
valid_counts_per_year = tar.groupby(tar.index.year).count()
invalid_years = valid_counts_per_year[valid_counts_per_year < 9].index
for year in invalid_years:
    tar[tar.index.year == year] = np.nan
# IB
era20c_hPa = pressure_era20c[:,7,9]/100
era20c_anomaly = era20c_hPa - era20c_hPa.mean()
era20c_anomaly = pd.Series(era20c_anomaly, index=dateera20c).resample('M').mean()
ib_0 = palma - (alpha * era20c_anomaly)
era5_hPa = pressure_era5[:,13,20]/100
era5_anomaly = era5_hPa - era5_hPa.mean()
era5_anomaly = pd.Series(era5_anomaly, index=dateera5).resample('M').mean()
ib_1 = palma - (alpha * era5_anomaly)
palma = ib_0.combine_first(ib_1)
# --
palma_y = palma.resample('Y').mean()
# GIA
trend = 0.33
time_passed = np.arange(palma_y.shape[0])[:]
cumulative_trend = time_passed * trend
palma_y = palma_y - cumulative_trend
palma_y2 = palma_y.dropna()
# GRD
grd = sea_barystatic[:,258,365]
grd = pd.Series(grd, index=datebary)
palma_y = palma_y - grd
palma_y = palma_y.dropna()

sea = palma_y.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean48 = imfs_sum / num_ensembles
imfs_mean48[2] = imfs_mean48[2] - np.mean(imfs_mean48[2])

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("Palma de Mallorca", y=0.83)
for n, imf in enumerate(imfs_mean48):
    plt.subplot(len(imfs_mean48)+1, 1, n+2)
    plt.plot(palma_y.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean48)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean48)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_palma.npy', imfs_mean48)
#np.save('imfs_palma_nogrd.npy', imfs_mean48)
imfs_palma = np.load('path/imfs_palma.npy')
imfs_palma_nogrd = np.load('path/imfs_palma_nogrd.npy')

# - - - - - - - - - - - - - - - - -  --  -
series5 = [(pal_y.index[:], ((imfs_palermo[1])[:])/10, 'pink', 'Palermo'),
          (nap_y.index[:], ((imfs_napoli[1])[:])/10, 'cyan', 'Napoli'),
          (cag_y.index[:], ((imfs_cagliari[1])[:])/10, 'red', 'Cagliari'),
          (civ_y.index[:], ((imfs_civitavecchia[1])[:])/10, 'black', 'Civitavecchia'),
          (gen_y.index[:], ((imfs_genova[1])[:])/10, 'blue', 'Genova'),
          (mau_y.index[:], ((imfs_portomaurizio[1])[:])/10, 'orange', 'Porto Maurizio'),
          (tou_y.index[:], ((imfs_toulon[1])[:])/10, 'magenta', 'Toulon'),
          (mar_y.index[:], ((imfs_marseille[1])[:])/10, 'gray', 'Marseille'),
          (sete_y.index[:], ((imfs_sete[1])[:])/10, 'green', 'Sete'),
          (est_y.index[:], ((imfs_estartit[1])[:])/10, 'lime', "L'Estartit"),
          (barc_y.index[:], ((imfs_barcelona[1])[:])/10, 'brown', 'Barcelona'),
          (vale_y.index[:], ((imfs_valencia[1])[:])/10, 'yellow', 'Valencia'),
          (ali_y.index[:], ((imfs_alicante[1])[:])/10, 'violet', 'Alicante'),
          (mal_y.index[:], ((imfs_malaga[1])[:])/10, 'purple', 'Malaga'),
          (gib_y.index[:], ((imfs_gibraltar[1])[:])/10, 'gold', 'Gibraltar'),
          (alg_y.index[:], ((imfs_algeciras[1])[:])/10, 'darkred', 'Algeciras'),
          (tar_y.index[:], ((imfs_tarifa[1])[:])/10, 'darkblue', 'Tarifa'),
          (ceu_y.index[:], ((imfs_ceuta[1])[:])/10, 'turquoise', 'Ceuta'),
          (palma_y.index[:], ((imfs_palma[1])[:])/10, 'grey', 'Palma de Mallorca')
          ]

plt.figure(figsize=(26,8), dpi=300)
for serie in series5:
    idx, data, color, label = serie
    idx = idx - pd.DateOffset(months=11)
    plt.plot(idx, data, label=label, color=color, linewidth=2)
    maxima = argrelextrema(data, np.greater)
    minima = argrelextrema(data, np.less)
    for max_idx in maxima[0]:
        plt.axvspan(idx[max_idx] - timedelta(365.25/2), idx[max_idx] + timedelta(365.25/2), color='r', alpha=0.1)
    for min_idx in minima[0]:
        plt.axvspan(idx[min_idx] - timedelta(365.25/2), idx[min_idx] + timedelta(365.25/2), color='b', alpha=0.1)
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))  
plt.gca().xaxis.set_minor_locator(mdates.YearLocator()) 
plt.xlabel('time', fontsize=16)
plt.ylabel('sea level (cm)', fontsize=16)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
date_bande = ['1991.5', '1997.5', '2006.5', '2011.5', '2017.5']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(tyr_basin.index, tyr_basin*100, linestyle='--', linewidth=3, label='Ionian mean from SA')  # Convertito da m a cm
plt.legend(handlelength=1, fontsize=16, framealpha=1, loc='upper right', ncol=9, facecolor='white')
plt.show()

dfs = [pd.DataFrame(data, index=idx) for idx, data, _, _ in series5]
aligned_dfs = pd.concat(dfs, axis=1)
mean_series = aligned_dfs.mean(axis=1)
mean_series = mean_series.shift(freq='-11M')
max_series = aligned_dfs.max(axis=1)
min_series = aligned_dfs.min(axis=1)

plt.figure(figsize=(17,5), dpi=300)
maxima_mean = argrelextrema(mean_series.values, np.greater)[0]
minima_mean = argrelextrema(mean_series.values, np.less)[0]
combined = sorted(list(maxima_mean) + list(minima_mean))
combined = [0] + combined + [len(mean_series)-1]
colors = ["#56B4E9","#E69F00",]
for i in range(len(combined)-1):
    start_idx = combined[i]
    end_idx = combined[i+1]
    plt.axvspan(mean_series.index[start_idx], mean_series.index[end_idx], color=colors[i % 2], alpha=0.3)
for max_idx in maxima_mean:
    plt.axvspan(mean_series.index[max_idx] - timedelta(365.25/2),
                mean_series.index[max_idx] + timedelta(365.25/2),
                color='white', alpha=1)
for min_idx in minima_mean:
    plt.axvspan(mean_series.index[min_idx] - timedelta(365.25/2),
                mean_series.index[min_idx] + timedelta(365.25/2),
                color='white', alpha=1)
std_dev_series = aligned_dfs.std(axis=1)
std_dev_series = std_dev_series.shift(freq='-11M')
plt.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4)
plt.plot(mean_series.index, mean_series, color='black', label = r'TG ensemble mean $\pm 1\sigma$', linewidth=2)
start_year = datetime(1900, 1, 1)
end_year = datetime(2018, 1, 31)
plt.gca().set_xlim([start_year, end_year])
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))
plt.gca().xaxis.set_minor_locator(mdates.YearLocator(1))
plt.xlabel('time', fontsize=20)
plt.ylabel('sea level (cm)', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
date_bande = ['1993', '1997', '2006', '2010', '2016']
for data in date_bande:
    year = int(float(data))
    month = int((float(data) - year) * 12 + 1)
    data_datetime = datetime(year, month, 1)
    plt.axvline(data_datetime, color='black', linestyle='--', linewidth=2)
plt.plot(western_med.index, western_med*100, linestyle='--', linewidth=3, label='SA basin mean', color='red')
plt.title('Western Mediterranean', fontsize=20)
plt.legend(handlelength=1.5, fontsize=20, framealpha=1, loc='upper center', ncol=9, facecolor='white')
plt.show()

print("Maxima dates:")
for idx in maxima_mean:
    print(mean_series.index[idx].date())
print("\nMinima dates:")
for idx in minima_mean:
    print(mean_series.index[idx].date())

series5_nogrd = [(pal_y.index[:], ((imfs_palermo_nogrd[1])[:])/10, 'pink', 'Palermo'),
          (nap_y.index[:], ((imfs_napoli_nogrd[1])[:])/10, 'cyan', 'Napoli'),
          (cag_y.index[:], ((imfs_cagliari_nogrd[1])[:])/10, 'red', 'Cagliari'),
          (civ_y.index[:], ((imfs_civitavecchia_nogrd[1])[:])/10, 'black', 'Civitavecchia'),
          (gen_y2.index[:], ((imfs_genova_nogrd[1])[:])/10, 'blue', 'Genova'),
          (mau_y.index[:], ((imfs_portomaurizio_nogrd[1])[:])/10, 'orange', 'Porto Maurizio'),
          (tou_y2.index[:], ((imfs_toulon_nogrd[1])[:])/10, 'magenta', 'Toulon'),
          (mar_y2.index[:], ((imfs_marseille_nogrd[1])[:])/10, 'gray', 'Marseille'),
          (sete_y2.index[:], ((imfs_sete_nogrd[1])[:])/10, 'green', 'Sete'),
          (est_y2.index[:], ((imfs_estartit_nogrd[1])[:])/10, 'lime', "L'Estartit"),
          (barc_y2.index[:], ((imfs_barcelona_nogrd[1])[:])/10, 'brown', 'Barcelona'),
          (vale_y2.index[:], ((imfs_valencia_nogrd[1])[:])/10, 'yellow', 'Valencia'),
          (ali_y2.index[:], ((imfs_alicante_nogrd[1])[:])/10, 'violet', 'Alicante'),
          (mal_y2.index[:], ((imfs_malaga_nogrd[1])[:])/10, 'purple', 'Malaga'),
          (gib_y.index[:], ((imfs_gibraltar_nogrd[1])[:])/10, 'gold', 'Gibraltar'),
          (alg_y.index[:], ((imfs_algeciras_nogrd[1])[:])/10, 'darkred', 'Algeciras'),
          (tar_y2.index[:], ((imfs_tarifa_nogrd[1])[:])/10, 'darkblue', 'Tarifa'),
          (ceu_y.index[:], ((imfs_ceuta_nogrd[1])[:])/10, 'turquoise', 'Ceuta'),
          (palma_y2.index[:], ((imfs_palma_nogrd[1])[:])/10, 'grey', 'Palma de Mallorca')
          ]



#--------------------------------------------------------------
#----------------------------------------------------------------
# MODE 1 CHARACTERISTICS

series1_nogrd_1 = [(tri_y2.index[:], ((imfs_trieste_nogrd[0])[:])/10, 'orange', 'Trieste'),
          (ven_y2.index[:], ((imfs_venice_nogrd[0])[:])/10, 'blue', 'Venice'),
          (rav_y.index[:], ((imfs_ravenna_nogrd[0])[:])/10, 'green', 'Porto Corsini'),
          (rov_y.index[:], ((imfs_rovinj_nogrd[0])[:])/10, 'red', 'Rovinj'),
          (bak_y2[:].index, ((imfs_bakar_nogrd[0])[:])/10, 'magenta', 'Bakar'),
          (spl_y[:].index, ((imfs_split_nogrd[0])[:])/10, 'black', 'Split'),
          (dub_y.index[:], ((imfs_dubrovnik_nogrd[0])[:])/10, 'cyan', 'Dubrovnik'),
          (rav_y_old.index[:], ((imfs_ravenna_old_nogrd[0])[:])/10, 'green', ''),
          (zad_y.index[:], ((imfs_zadar_nogrd[0])[:])/10, 'gold', 'Zadar'),
          (bar_y.index[:], ((imfs_bar_nogrd[0])[:])/10, 'violet', 'Bar')
          ]
series2_nogrd_1 = [(pre_y2.index[:], ((imfs_preveza_nogrd[0])[:])/10, 'orange', 'Preveza'),
          (lev_y2.index[:], ((imfs_levkas_nogrd[0])[:])/10, 'green', 'Levkas'),
          (kat_y2.index[:], ((imfs_katakolon_nogrd[0])[:])/10, 'red', 'Katakolon'),
          (val_y2.index[:], ((imfs_valletta_nogrd[0])[:])/10, 'black', 'La Valletta'),
          (kal_y.index[:], ((imfs_kalamai_nogrd[0])[:])/10, 'magenta', 'Kalamai')
          ]
series3_nogrd_1 = [(ant_y.index[:], ((imfs_antalya_nogrd[0])[:])/10, 'black', 'Antalya'),
          (ale_y.index[:62], ((imfs_alexandria_nogrd[0])[:62])/10, 'green', 'Alexandria'),
          (had_y2.index[:], ((imfs_hadera_nogrd[0])[:])/10, 'red', 'Hadera'),
          (ant_y_new.index[:], ((imfs_antalya_new_nogrd[0])[:])/10, 'black', ''),
          (said_y.index[:], ((imfs_portsaid_nogrd[0])[:])/10, 'orange', 'Port Said')
          ]
series4_nogrd_1 = [(ler_y2.index[:], ((imfs_leros_nogrd[0])[:])/10, 'black', 'Leros'),
          (khi_y.index[:], ((imfs_khios_nogrd[0])[:])/10, 'green', 'Khios'),
          (alex_y2.index[:], ((imfs_alexandroupolis_nogrd[0])[:])/10, 'red', 'Alexandroupolis'),
          (the_y.index[:], ((imfs_thessaloniki_nogrd[0])[:])/10, 'blue', 'Thessaloniki'),
          (kha_y2.index[:], ((imfs_khalkis_nogrd[0])[:])/10, 'orange', 'Khalkis'),
          (pir_y2.index[:], ((imfs_piraievs_nogrd[0])[:])/10, 'cyan', 'Piraievs'),
          (sir_y2.index[:], ((imfs_siros_nogrd[0])[:])/10, 'purple', 'Siros'),
          (bod_y.index[:], ((imfs_bodrum_nogrd[0])[:])/10, 'magenta', 'Bodrum'),
          (izm_y.index[:], ((imfs_izmir_nogrd[0])[:])/10, 'gold', 'Izmir')
          ]
series5_nogrd_1 = [(pal_y.index[:], ((imfs_palermo_nogrd[0])[:])/10, 'pink', 'Palermo'),
          (nap_y.index[:], ((imfs_napoli_nogrd[0])[:])/10, 'cyan', 'Napoli'),
          (cag_y.index[:], ((imfs_cagliari_nogrd[0])[:])/10, 'red', 'Cagliari'),
          (civ_y.index[:], ((imfs_civitavecchia_nogrd[0])[:])/10, 'black', 'Civitavecchia'),
          (gen_y2.index[:], ((imfs_genova_nogrd[0])[:])/10, 'blue', 'Genova'),
          (mau_y.index[:], ((imfs_portomaurizio_nogrd[0])[:])/10, 'orange', 'Porto Maurizio'),
          (tou_y2.index[:], ((imfs_toulon_nogrd[0])[:])/10, 'magenta', 'Toulon'),
          (mar_y2.index[:], ((imfs_marseille_nogrd[0])[:])/10, 'gray', 'Marseille'),
          (sete_y2.index[:], ((imfs_sete_nogrd[0])[:])/10, 'green', 'Sete'),
          (est_y2.index[:], ((imfs_estartit_nogrd[0])[:])/10, 'lime', "L'Estartit"),
          (barc_y2.index[:], ((imfs_barcelona_nogrd[0])[:])/10, 'brown', 'Barcelona'),
          (vale_y2.index[:], ((imfs_valencia_nogrd[0])[:])/10, 'yellow', 'Valencia'),
          (ali_y2.index[:], ((imfs_alicante_nogrd[0])[:])/10, 'violet', 'Alicante'),
          (mal_y2.index[:], ((imfs_malaga_nogrd[0])[:])/10, 'purple', 'Malaga'),
          (gib_y.index[:], ((imfs_gibraltar_nogrd[0])[:])/10, 'gold', 'Gibraltar'),
          (alg_y.index[:], ((imfs_algeciras_nogrd[0])[:])/10, 'darkred', 'Algeciras'),
          (tar_y2.index[:], ((imfs_tarifa_nogrd[0])[:])/10, 'darkblue', 'Tarifa'),
          (ceu_y.index[:], ((imfs_ceuta_nogrd[0])[:])/10, 'turquoise', 'Ceuta'),
          (palma_y2.index[:], ((imfs_palma_nogrd[0])[:])/10, 'grey', 'Palma de Mallorca')
          ]

adria_basin_1=pd.read_csv('path/adria_basin_1.txt',\
                 delim_whitespace=True,header=None)[:]
adria_basin_1.index = datesat
adria_basin_1 = adria_basin_1[0]
adria_basin_1.index = adria_basin_1.index - pd.DateOffset(months=11)
ion_basin_1=pd.read_csv('path/ion_basin_1.txt',\
                 delim_whitespace=True,header=None)[:]
ion_basin_1.index = datesat
ion_basin_1 = ion_basin_1[0]
ion_basin_1.index = ion_basin_1.index - pd.DateOffset(months=11)
lev_basin_1=pd.read_csv('path/lev_basin_1.txt',\
                 delim_whitespace=True,header=None)[:]
lev_basin_1.index = datesat
lev_basin_1 = lev_basin_1[0]
lev_basin_1.index = lev_basin_1.index - pd.DateOffset(months=11)
egeo_basin_1=pd.read_csv('path/egeo_basin_1.txt',\
                 delim_whitespace=True,header=None)[:]
egeo_basin_1.index = datesat
egeo_basin_1 = egeo_basin_1[0]
egeo_basin_1.index = egeo_basin_1.index - pd.DateOffset(months=11)
tyr_basin_1=pd.read_csv('path/tyr_basin_1.txt',\
                 delim_whitespace=True,header=None)[:]
tyr_basin_1.index = datesat
tyr_basin_1 = tyr_basin_1[0]
tyr_basin_1.index = tyr_basin_1.index - pd.DateOffset(months=11)
west_basin_1=pd.read_csv('path/west_basin_1.txt',\
                 delim_whitespace=True,header=None)[:]
west_basin_1.index = datesat
west_basin_1 = west_basin_1[0]
west_basin_1.index = west_basin_1.index - pd.DateOffset(months=11)
scm_basin_1=pd.read_csv('path/scm_basin_1.txt',\
                 delim_whitespace=True,header=None)[:]
scm_basin_1.index = datesat
scm_basin_1 = scm_basin_1[0]
scm_basin_1.index = scm_basin_1.index - pd.DateOffset(months=11)

western_med_1 = (west_basin_1 + tyr_basin_1) /2
ion_basin_1 = (ion_basin_1 + scm_basin_1) /2
med_1 = (western_med_1 + ion_basin_1 + adria_basin_1 + lev_basin_1 + egeo_basin_1) /5


# FIGURE MODE 1 WITHOUT GRD CORRECTION APPLIED
date_adria = ['1987','1990','1998','2007','2010','2017','2020']
date_ion = ['1987','1993','1997','2008','2010','2017','2020']
date_lev = ['1987','1993','1997','2008','2010','2017','2020']
date_aeg = ['1987','1993','1999','2008','2010','2017','2020']
date_west = ['1989','1992','1997','2005','2010','2017','2020']
date_med = ['1987','1993','1998','2008','2010','2017','2020']
all_date_bande_1 = [date_adria, date_ion, date_lev, date_aeg, date_west, date_med]
all_series_nogrd_1 = [series1_nogrd_1, series2_nogrd_1, series3_nogrd_1, series4_nogrd_1, series5_nogrd_1]
all_red_series_1 = [adria_basin_1, ion_basin_1, lev_basin_1, egeo_basin_1, western_med_1, med_1]
all_means_1 = []
all_std_devs_1 = []
for series_data_1 in all_series_nogrd_1:
    dfs_1 = [pd.DataFrame(data, index=idx - pd.DateOffset(months=11)) for idx, data, _, _ in series_data_1]
    aligned_dfs_1 = pd.concat(dfs_1, axis=1)
    mean_series_1 = aligned_dfs_1.mean(axis=1)
    std_dev_series_1 = aligned_dfs_1.std(axis=1)
    all_means_1.append(mean_series_1)
    all_std_devs_1.append(std_dev_series_1)
mediterranean_mean_1 = pd.concat(all_means_1, axis=1).mean(axis=1)
mediterranean_std_dev_1 = pd.concat(all_std_devs_1, axis=1).std(axis=1)
all_series_nogrd_1.append(mediterranean_mean_1)

all_series_nogrd_1 = [('adria', all_series_nogrd_1[0]),
                        ('ion', all_series_nogrd_1[1]),
                        ('lev', all_series_nogrd_1[2]),
                        ('aeg', all_series_nogrd_1[3]),
                        ('west', all_series_nogrd_1[4]),
                        ('med', all_series_nogrd_1[5])]

def plot_on_axis(ax, name, series_data_1, red_series_1, date_bande, title, xlabel=True, ylabel=True, custom_mean_series_1=None, custom_std_dev_series_1=None):
    if isinstance(series_data_1, list):
        dfs = [pd.DataFrame(data, index=idx - pd.DateOffset(months=11)) for idx, data, _, _ in series_data_1]
        aligned_dfs = pd.concat(dfs, axis=1)
        mean_series = aligned_dfs.mean(axis=1)
        std_dev_series = aligned_dfs.std(axis=1)
    else:
        mean_series = series_data_1
        if custom_mean_series_1 is not None and custom_std_dev_series_1 is not None:
            std_dev_series = custom_std_dev_series_1
        else:
            std_dev_series = pd.Series(np.zeros_like(mean_series), index=mean_series.index)
    
    maxima_mean = argrelextrema(mean_series.values, np.greater, order = 1)[0]
    minima_mean = argrelextrema(mean_series.values, np.less, order = 1)[0]
    combined = sorted(list(maxima_mean) + list(minima_mean))
    combined = [0] + combined + [len(mean_series)-1]
    first_max = mean_series.index[maxima_mean[0]]
    first_min = mean_series.index[minima_mean[0]]
    if first_max < first_min:
        colors = ["#E69F00","#56B4E9"]
    else:
        colors = ["#56B4E9","#E69F00"]
    for i in range(len(combined)-1):
        start_idx = combined[i]
        end_idx = combined[i+1]
        ax.axvspan(mean_series.index[start_idx], mean_series.index[end_idx], color=colors[i % 2], alpha=0.3)
    for max_idx in maxima_mean:
        ax.axvspan(mean_series.index[max_idx] - timedelta(365.25/2),
                   mean_series.index[max_idx] + timedelta(365.25/2),
                   color='white', alpha=1)
    for min_idx in minima_mean:
        ax.axvspan(mean_series.index[min_idx] - timedelta(365.25/2),
                   mean_series.index[min_idx] + timedelta(365.25/2),
                   color='white', alpha=1)
    ax.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4)
    ax.plot(mean_series.index, mean_series, color='black', linewidth=2)
    if red_series_1 is not None:
        ax.plot(red_series_1.index, red_series_1*100, linestyle='--', linewidth=3, color='red')
    for data in date_bande:
        year = int(float(data))
        month = int((float(data) - year) * 12 + 1)
        data_datetime = datetime(year, month, 1)
        ax.axvline(data_datetime, color='black', linestyle='--', linewidth=1.5)
    ax.set_xlim(datetime(1900, 1, 1), datetime(2022, 6, 30))
    ax.set_yticks(np.arange(int(min(ax.get_ylim())), int(max(ax.get_ylim()))+1, 2))
    if xlabel:
        ax.set_xlabel('time', fontsize=14)
    if ylabel:
        ax.set_ylabel('IMF1 sea level (cm)', fontsize=14)
    ax.xaxis.set_major_locator(mdates.YearLocator(10))
    ax.xaxis.set_minor_locator(mdates.YearLocator(1))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
    ax.set_title(title, fontsize=14)
    ax.tick_params(axis='x', labelsize=12)
    ax.tick_params(axis='y', labelsize=12)
    ax.axhline(y=0, color='black', linestyle='--', linewidth=0.5)

# 0 adriatic ; 1 Ionian ; 2 levantine ; 3 aegean ; 4 west ; 5 med
order2 = [5, 0, 4, 2, 3, 1]
ordered_series_nogrd_1 = [all_series_nogrd_1[i] for i in order2]
all_red_series_1 = [all_red_series_1[i] for i in order2]
all_date_bande_1 = [all_date_bande_1[i] for i in order2]

fig, axes = plt.subplots(nrows=6, ncols=1, figsize=(14,11), dpi=100)
titles = ["Mediterranean", "Adriatic", "Western", "Levantine", "Aegean", "Ionian"]
axes = axes.flatten()
label_flags = [(True, False), (True, False), (True, False), (True, False), (True, False), (True, True)]
for ax, (name, series_data), red_series, date_bande, title, (ylabel, xlabel) in zip(axes, ordered_series_nogrd_1, all_red_series_1, all_date_bande_1, titles, label_flags):
    if title == "Mediterranean":
        plot_on_axis(ax, name, series_data, red_series, date_bande, title, xlabel, ylabel, custom_mean_series_1=mediterranean_mean_1, custom_std_dev_series_1=mediterranean_std_dev_1)
    else:
        plot_on_axis(ax, name, series_data, red_series, date_bande, title, xlabel, ylabel)
plt.tight_layout()
plt.show()


# - - - 

def dominant_periodicity(data):
    spectrum = np.fft.fft(data)
    frequencies = np.fft.fftfreq(len(data))
    freq = abs(frequencies[np.argmax(np.abs(spectrum[1:])) + 1])
    period = 1 / freq
    return period
def calculate_amplitude(data):
    return np.max(data) - np.min(data)
groups = [series1_nogrd_1, series2_nogrd_1, series3_nogrd_1, series4_nogrd_1, series5_nogrd_1]
group_names = ["Adriatic", "Ionian", "Levantine", "Aegean", "Western"]
for idx, group in enumerate(groups):
    all_series_in_group = pd.concat([pd.Series(data[1]) for data in group], axis=1)
    mean_series = all_series_in_group.mean(axis=1)
    individual_periods = [dominant_periodicity(data[1]) for data in group]
    mean_period = np.mean(individual_periods)
    period_std_dev = np.std(individual_periods)
    amplitude = calculate_amplitude(mean_series)
    individual_amplitudes = [calculate_amplitude(pd.Series(data[1])) for data in group]
    amplitude_std_dev = np.std(individual_amplitudes)
    print(f"{group_names[idx]} - average period: {mean_period:.1f} years ± {period_std_dev:.1f}, average amplitude: {amplitude:.1f} ± {amplitude_std_dev:.1f}")
all_data = pd.concat([pd.Series(data[1]) for group in groups for data in group], axis=1)
mean_mediterranean_series = all_data.mean(axis=1)
mediterranean_periods = [dominant_periodicity(data[1]) for group in groups for data in group]
mean_mediterranean_period = np.mean(mediterranean_periods)
mediterranean_period_std_dev = np.std(mediterranean_periods)
mediterranean_amplitude = calculate_amplitude(mean_mediterranean_series)
individual_amplitudes_mediterranean = [calculate_amplitude(pd.Series(data[1])) for group in groups for data in group]
mediterranean_amplitude_std_dev = np.std(individual_amplitudes_mediterranean)
print(f"Mediterranean - average period: {mean_mediterranean_period:.1f} years ± {mediterranean_period_std_dev:.1f}, average amplitude: {mediterranean_amplitude:.1f} ± {mediterranean_amplitude_std_dev:.1f}")


# FIGURE MODE 2 WITHOUT GRD CORRECTION APPLIED

series1_nogrd = [(tri_y2.index[:], ((imfs_trieste_nogrd[1])[:])/10, 'orange', 'Trieste'),
          (ven_y2.index[:], ((imfs_venice_nogrd[1])[:])/10, 'blue', 'Venice'),
          (rav_y.index[:], ((imfs_ravenna_nogrd[1])[:])/10, 'green', 'Porto Corsini'),
          (rov_y.index[:], ((imfs_rovinj_nogrd[1])[:])/10, 'red', 'Rovinj'),
          (bak_y2[:].index, ((imfs_bakar_nogrd[1])[:])/10, 'magenta', 'Bakar'),
          (spl_y[:].index, ((imfs_split_nogrd[1])[:])/10, 'black', 'Split'),
          (dub_y.index[:], ((imfs_dubrovnik_nogrd[1])[:])/10, 'cyan', 'Dubrovnik'),
          (rav_y_old.index[:], ((imfs_ravenna_old_nogrd[1])[:])/10, 'green', ''),
          (zad_y.index[:], ((imfs_zadar_nogrd[1])[:])/10, 'gold', 'Zadar'),
          (bar_y.index[:], ((imfs_bar_nogrd[1])[:])/10, 'violet', 'Bar')
          ]
series2_nogrd = [(pre_y2.index[:], ((imfs_preveza_nogrd[1])[:])/10, 'orange', 'Preveza'),
          (lev_y2.index[:], ((imfs_levkas_nogrd[1])[:])/10, 'green', 'Levkas'),
          (kat_y2.index[:], ((imfs_katakolon_nogrd[1])[:])/10, 'red', 'Katakolon'),
          (val_y2.index[:], ((imfs_valletta_nogrd[1])[:])/10, 'black', 'La Valletta'),
          (kal_y.index[:], ((imfs_kalamai_nogrd[1])[:])/10, 'magenta', 'Kalamai')
          ]
series3_nogrd = [(ant_y.index[:], ((imfs_antalya_nogrd[1])[:])/10, 'black', 'Antalya'),
          (ale_y.index[:62], ((imfs_alexandria_nogrd[1])[:62])/10, 'green', 'Alexandria'),
          (had_y2.index[:], ((imfs_hadera_nogrd[1])[:])/10, 'red', 'Hadera'),
          (ant_y_new.index[:], ((imfs_antalya_new_nogrd[1])[:])/10, 'black', ''),
          (said_y.index[:], ((imfs_portsaid_nogrd[1])[:])/10, 'orange', 'Port Said')
          ]
series4_nogrd = [(ler_y2.index[:], ((imfs_leros_nogrd[1])[:])/10, 'black', 'Leros'),
          (khi_y.index[:], ((imfs_khios_nogrd[1])[:])/10, 'green', 'Khios'),
          (alex_y2.index[:], ((imfs_alexandroupolis_nogrd[1])[:])/10, 'red', 'Alexandroupolis'),
          (the_y.index[:], ((imfs_thessaloniki_nogrd[1])[:])/10, 'blue', 'Thessaloniki'),
          (kha_y2.index[:], ((imfs_khalkis_nogrd[1])[:])/10, 'orange', 'Khalkis'),
          (pir_y2.index[:], ((imfs_piraievs_nogrd[1])[:])/10, 'cyan', 'Piraievs'),
          (sir_y2.index[:], ((imfs_siros_nogrd[1])[:])/10, 'purple', 'Siros'),
          (bod_y.index[:], ((imfs_bodrum_nogrd[1])[:])/10, 'magenta', 'Bodrum'),
          (izm_y.index[:], ((imfs_izmir_nogrd[1])[:])/10, 'gold', 'Izmir')
          ]
series5_nogrd = [(pal_y.index[:], ((imfs_palermo_nogrd[1])[:])/10, 'pink', 'Palermo'),
          (nap_y.index[:], ((imfs_napoli_nogrd[1])[:])/10, 'cyan', 'Napoli'),
          (cag_y.index[:], ((imfs_cagliari_nogrd[1])[:])/10, 'red', 'Cagliari'),
          (civ_y.index[:], ((imfs_civitavecchia_nogrd[1])[:])/10, 'black', 'Civitavecchia'),
          (gen_y2.index[:], ((imfs_genova_nogrd[1])[:])/10, 'blue', 'Genova'),
          (mau_y.index[:], ((imfs_portomaurizio_nogrd[1])[:])/10, 'orange', 'Porto Maurizio'),
          (tou_y2.index[:], ((imfs_toulon_nogrd[1])[:])/10, 'magenta', 'Toulon'),
          (mar_y2.index[:], ((imfs_marseille_nogrd[1])[:])/10, 'gray', 'Marseille'),
          (sete_y2.index[:], ((imfs_sete_nogrd[1])[:])/10, 'green', 'Sete'),
          (est_y2.index[:], ((imfs_estartit_nogrd[1])[:])/10, 'lime', "L'Estartit"),
          (barc_y2.index[:], ((imfs_barcelona_nogrd[1])[:])/10, 'brown', 'Barcelona'),
          (vale_y2.index[:], ((imfs_valencia_nogrd[1])[:])/10, 'yellow', 'Valencia'),
          (ali_y2.index[:], ((imfs_alicante_nogrd[1])[:])/10, 'violet', 'Alicante'),
          (mal_y2.index[:], ((imfs_malaga_nogrd[1])[:])/10, 'purple', 'Malaga'),
          (gib_y.index[:], ((imfs_gibraltar_nogrd[1])[:])/10, 'gold', 'Gibraltar'),
          (alg_y.index[:], ((imfs_algeciras_nogrd[1])[:])/10, 'darkred', 'Algeciras'),
          (tar_y2.index[:], ((imfs_tarifa_nogrd[1])[:])/10, 'darkblue', 'Tarifa'),
          (ceu_y.index[:], ((imfs_ceuta_nogrd[1])[:])/10, 'turquoise', 'Ceuta'),
          (palma_y2.index[:], ((imfs_palma_nogrd[1])[:])/10, 'grey', 'Palma de Mallorca')
          ]

date_adria = ['1987','1991','1997','2006','2010','2017','2020']
date_ion = ['1987','1990','1998','2007','2010','2016','2020']
date_lev = ['1987','1992','1997','2007','2011','2016','2021']
date_aeg = ['1988','1993','1999','2007','2011','2017','2021']
date_west = ['1989','1993','1997','2006','2010','2016','2020']
date_med = ['1987','1992','1998','2007','2010','2017','2020']
all_date_bande = [date_adria, date_ion, date_lev, date_aeg, date_west, date_med]
all_series_nogrd = [series1_nogrd, series2_nogrd, series3_nogrd, series4_nogrd, series5_nogrd]
all_red_series = [adria_basin, ion_basin_combined, lev_basin, egeo_basin, western_med, med]
all_red_series_std = [adria_basin_std, ion_basin_combined_std, lev_basin_std, egeo_basin_std, western_med_std, med_std]
all_means = []
all_std_devs = []
for series_data in all_series_nogrd:
    dfs = [pd.DataFrame(data, index=idx - pd.DateOffset(months=11)) for idx, data, _, _ in series_data]
    aligned_dfs = pd.concat(dfs, axis=1)
    mean_series = aligned_dfs.mean(axis=1)
    std_dev_series = aligned_dfs.std(axis=1)
    all_means.append(mean_series)
    all_std_devs.append(std_dev_series)
mediterranean_mean = pd.concat(all_means, axis=1).mean(axis=1)
mediterranean_std_dev = pd.concat(all_std_devs, axis=1).std(axis=1)
all_series_nogrd.append(mediterranean_mean)

all_series_nogrd = [('adria', all_series_nogrd[0]),
                        ('ion', all_series_nogrd[1]),
                        ('lev', all_series_nogrd[2]),
                        ('aeg', all_series_nogrd[3]),
                        ('west', all_series_nogrd[4]),
                        ('med', all_series_nogrd[5])]

def plot_on_axis(ax, name, series_data, red_series, red_series_std, date_bande, title, xlabel=True, ylabel=True, custom_mean_series=None, custom_std_dev_series=None):
    if isinstance(series_data, list):
        dfs = [pd.DataFrame(data, index=idx - pd.DateOffset(months=11)) for idx, data, _, _ in series_data]
        aligned_dfs = pd.concat(dfs, axis=1)
        mean_series = aligned_dfs.mean(axis=1)
        std_dev_series = aligned_dfs.std(axis=1)
    else:
        mean_series = series_data
        if custom_mean_series is not None and custom_std_dev_series is not None:
            std_dev_series = custom_std_dev_series
        else:
            std_dev_series = pd.Series(np.zeros_like(mean_series), index=mean_series.index)
    maxima_mean = argrelextrema(mean_series.values, np.greater, order = 1)[0]
    minima_mean = argrelextrema(mean_series.values, np.less, order = 1)[0]
    combined = sorted(list(maxima_mean) + list(minima_mean))
    combined = [0] + combined + [len(mean_series)-1]
    first_max = mean_series.index[maxima_mean[0]]
    first_min = mean_series.index[minima_mean[0]]
    if first_max < first_min:
        colors = ["#E69F00","#56B4E9"]
    else:
        colors = ["#56B4E9","#E69F00"]
    for i in range(len(combined)-1):
        start_idx = combined[i]
        end_idx = combined[i+1]
        ax.axvspan(mean_series.index[start_idx], mean_series.index[end_idx], color=colors[i % 2], alpha=0.3)
    for max_idx in maxima_mean:
        ax.axvspan(mean_series.index[max_idx] - timedelta(365.25/2),
                   mean_series.index[max_idx] + timedelta(365.25/2),
                   color='white', alpha=1)
    for min_idx in minima_mean:
        ax.axvspan(mean_series.index[min_idx] - timedelta(365.25/2),
                   mean_series.index[min_idx] + timedelta(365.25/2),
                   color='white', alpha=1)
    ax.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4, edgecolor=None)
    ax.plot(mean_series.index, mean_series, color='black', linewidth=2)
    if red_series is not None:
        ax.plot(red_series.index, red_series*100, linestyle='--', linewidth=3, color='red')
        if red_series_std is not None:
            upper_bound = (red_series + red_series_std)*100
            lower_bound = (red_series - red_series_std)*100
            ax.fill_between(red_series.index, lower_bound, upper_bound, color='red', alpha=0.2, edgecolor=None)
    for data in date_bande:
        year = int(float(data))
        month = int((float(data) - year) * 12 + 1)
        data_datetime = datetime(year, month, 1)
        ax.axvline(data_datetime, color='black', linestyle='--', linewidth=1.5)
    ax.set_xlim(datetime(1900, 1, 1), datetime(2022, 4, 30))
    ax.set_yticks(np.arange(int(min(ax.get_ylim())), int(max(ax.get_ylim()))+1, 2))
    if xlabel:
        ax.set_xlabel('time', fontsize=14)
    if ylabel:
        ax.set_ylabel('IMF2 sea level (cm)', fontsize=13)
    ax.xaxis.set_major_locator(mdates.YearLocator(10))
    ax.xaxis.set_minor_locator(mdates.YearLocator(1))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
    ax.axhline(y=0, color='black', linestyle='--', linewidth=0.5)
    ax.set_title(title, fontsize=14)
    ax.tick_params(axis='x', labelsize=12)
    ax.tick_params(axis='y', labelsize=12)
    return mean_series, std_dev_series

# 0 adriatic ; 1 Ionian ; 2 levantine ; 3 aegean ; 4 west ; 5 med
order = [5, 0, 4, 2, 3, 1]
ordered_series_nogrd = [all_series_nogrd[i] for i in order]
ordered_red_series = [all_red_series[i] for i in order]
ordered_date_bande = [all_date_bande[i] for i in order]
ordered_red_series_std = [all_red_series_std[i] for i in order]

results = {}

fig, axes = plt.subplots(nrows=6, ncols=1, figsize=(12,10), dpi=100)
titles = ["Mediterranean", "Adriatic", "Western", "Levantine", "Aegean", "Ionian"]
axes = axes.flatten()
label_flags = [(True, False), (True, False), (True, False), (True, False), (True, False), (True, True)]
for ax, (name, series_data), red_series, red_series_std, date_bande, title, (ylabel, xlabel) in zip(axes, ordered_series_nogrd, ordered_red_series, ordered_red_series_std, ordered_date_bande, titles, label_flags):
    if title == "Mediterranean":
        mean_series, std_dev_series = plot_on_axis(ax, name, series_data, red_series, red_series_std, date_bande, title, xlabel, ylabel, custom_mean_series=mediterranean_mean, custom_std_dev_series=mediterranean_std_dev)
    else:
        mean_series, std_dev_series = plot_on_axis(ax, name, series_data, red_series, red_series_std, date_bande, title, xlabel, ylabel)
    results[title] = {"mean": mean_series, "std_dev": std_dev_series}
plt.tight_layout()
plt.show()

df_results = pd.concat({key: pd.DataFrame(val) for key, val in results.items()}, axis=1)


# - - - # - - - 

def dominant_periodicity(data):
    spectrum = np.fft.fft(data)
    frequencies = np.fft.fftfreq(len(data))
    freq = abs(frequencies[np.argmax(np.abs(spectrum[1:])) + 1])
    period = 1 / freq
    return period
def calculate_amplitude(data):
    return np.max(data) - np.min(data)
groups = [series1_nogrd, series2_nogrd, series3_nogrd, series4_nogrd, series5_nogrd]
group_names = ["Adriatic", "Ionian", "Levantine", "Aegean", "Western"]
for idx, group in enumerate(groups):
    all_series_in_group = pd.concat([pd.Series(data[1]) for data in group], axis=1)
    mean_series = all_series_in_group.mean(axis=1)
    individual_periods = [dominant_periodicity(data[1]) for data in group]
    mean_period = np.mean(individual_periods)
    period_std_dev = np.std(individual_periods)
    amplitude = calculate_amplitude(mean_series)
    individual_amplitudes = [calculate_amplitude(pd.Series(data[1])) for data in group]
    amplitude_std_dev = np.std(individual_amplitudes)
    print(f"{group_names[idx]} - average period: {mean_period:.1f} years ± {period_std_dev:.1f}, average amplitude: {amplitude:.1f} ± {amplitude_std_dev:.1f}")
all_data = pd.concat([pd.Series(data[1]) for group in groups for data in group], axis=1)
mean_mediterranean_series = all_data.mean(axis=1)
mediterranean_periods = [dominant_periodicity(data[1]) for group in groups for data in group]
mean_mediterranean_period = np.mean(mediterranean_periods)
mediterranean_period_std_dev = np.std(mediterranean_periods)
mediterranean_amplitude = calculate_amplitude(mean_mediterranean_series)
individual_amplitudes_mediterranean = [calculate_amplitude(pd.Series(data[1])) for group in groups for data in group]
mediterranean_amplitude_std_dev = np.std(individual_amplitudes_mediterranean)
print(f"Mediterranean - average period: {mean_mediterranean_period:.1f} years ± {mediterranean_period_std_dev:.1f}, average amplitude: {mediterranean_amplitude:.1f} ± {mediterranean_amplitude_std_dev:.1f}")

def get_maxima_minima(series_data):
    if isinstance(series_data, pd.DataFrame):
        mean_series = series_data.mean(axis=1)
    else: 
        dfs = [pd.DataFrame(data, index=idx) for idx, data, _, _ in series_data]
        aligned_dfs = pd.concat(dfs, axis=1)
        mean_series = aligned_dfs.mean(axis=1)
    maxima_mean_indices = argrelextrema(mean_series.values, np.greater, order=1)[0]
    minima_mean_indices = argrelextrema(mean_series.values, np.less, order=1)[0]
    maxima_dates = mean_series.index[maxima_mean_indices].tolist()
    minima_dates = mean_series.index[minima_mean_indices].tolist()
    return maxima_dates, minima_dates
maximaminima = {}
for idx, (name, series_data) in enumerate(all_series_nogrd[:-1]): 
    maxima_dates, minima_dates = get_maxima_minima(series_data)
    maximaminima[name] = {
        'maxima_dates': [date.year for date in maxima_dates],
        'minima_dates': [date.year for date in minima_dates],
    }
all_data = pd.concat([pd.DataFrame(data[1], index=data[0]) for group in groups for data in group], axis=1)
mean_mediterranean_series = all_data.mean(axis=1)
maxima_dates, minima_dates = get_maxima_minima(mean_mediterranean_series.to_frame())
maximaminima["Mediterranean"] = {
    'maxima_dates': [date.year for date in maxima_dates],
    'minima_dates': [date.year for date in minima_dates],
}
for region, values in maximaminima.items():
    print(f"\n{region.capitalize()} - Maxima dates:")
    for year in values['maxima_dates']:
        print(year)
    print(f"\n{region.capitalize()} - Minima dates:")
    for year in values['minima_dates']:
        print(year)





# FIGURE MODE 2 WITH GRD CORRECTION APPLIED

series1 = [(tri_y.index[:], ((imfs_trieste[1])[:])/10, 'orange', 'Trieste'),
          (ven_y.index[:], ((imfs_venice[1])[:])/10, 'blue', 'Venice'),
          (rav_y.index[:], ((imfs_ravenna[1])[:])/10, 'green', 'Porto Corsini'),
          (rov_y.index[:], ((imfs_rovinj[1])[:])/10, 'red', 'Rovinj'),
          (bak_y[:].index, ((imfs_bakar[1])[:])/10, 'magenta', 'Bakar'),
          (spl_y[:].index, ((imfs_split[1])[:])/10, 'black', 'Split'),
          (dub_y.index[:], ((imfs_dubrovnik[1])[:])/10, 'cyan', 'Dubrovnik'),
          (rav_y_old.index[:], ((imfs_ravenna_old[1])[:])/10, 'green', ''),
          (zad_y.index[:], ((imfs_zadar[1])[:])/10, 'gold', 'Zadar'),
          (bar_y.index[:], ((imfs_bar[1])[:])/10, 'violet', 'Bar')
          ]
series2 = [(pre_y.index[:], ((imfs_preveza[1])[:])/10, 'orange', 'Preveza'),
          (lev_y.index[:], ((imfs_levkas[1])[:])/10, 'green', 'Levkas'),
          (kat_y.index[:], ((imfs_katakolon[1])[:])/10, 'red', 'Katakolon'),
          (val_y.index[:], ((imfs_valletta[1])[:])/10, 'black', 'La Valletta'),
          (kal_y.index[:], ((imfs_kalamai[1])[:])/10, 'magenta', 'Kalamai')
          ]
series3 = [(ant_y.index[:], ((imfs_antalya[1])[:])/10, 'black', 'Antalya'),
          (ale_y.index[:62], ((imfs_alexandria[1])[:62])/10, 'green', 'Alexandria'),
          (had_y.index[:], ((imfs_hadera[1])[:])/10, 'red', 'Hadera'),
          (ant_y_new.index[:], ((imfs_antalya_new[1])[:])/10, 'black', ''),
          (said_y.index[:], ((imfs_portsaid[1])[:])/10, 'orange', 'Port Said')
          ]
series4 = [(ler_y.index[:], ((imfs_leros[1])[:])/10, 'black', 'Leros'),
          (khi_y.index[:], ((imfs_khios[1])[:])/10, 'green', 'Khios'),
          (alex_y.index[:], ((imfs_alexandroupolis[1])[:])/10, 'red', 'Alexandroupolis'),
          (the_y.index[:], ((imfs_thessaloniki[1])[:])/10, 'blue', 'Thessaloniki'),
          (kha_y.index[:], ((imfs_khalkis[1])[:])/10, 'orange', 'Khalkis'),
          (pir_y.index[:], ((imfs_piraievs[1])[:])/10, 'cyan', 'Piraievs'),
          (sir_y.index[:], ((imfs_siros[1])[:])/10, 'purple', 'Siros'),
          (bod_y.index[:], ((imfs_bodrum[1])[:])/10, 'magenta', 'Bodrum'),
          (izm_y.index[:], ((imfs_izmir[1])[:])/10, 'gold', 'Izmir')
          ]
series5 = [(pal_y.index[:], ((imfs_palermo[1])[:])/10, 'pink', 'Palermo'),
          (nap_y.index[:], ((imfs_napoli[1])[:])/10, 'cyan', 'Napoli'),
          (cag_y.index[:], ((imfs_cagliari[1])[:])/10, 'red', 'Cagliari'),
          (civ_y.index[:], ((imfs_civitavecchia[1])[:])/10, 'black', 'Civitavecchia'),
          (gen_y.index[:], ((imfs_genova[1])[:])/10, 'blue', 'Genova'),
          (mau_y.index[:], ((imfs_portomaurizio[1])[:])/10, 'orange', 'Porto Maurizio'),
          (tou_y.index[:], ((imfs_toulon[1])[:])/10, 'magenta', 'Toulon'),
          (mar_y.index[:], ((imfs_marseille[1])[:])/10, 'gray', 'Marseille'),
          (sete_y.index[:], ((imfs_sete[1])[:])/10, 'green', 'Sete'),
          (est_y.index[:], ((imfs_estartit[1])[:])/10, 'lime', "L'Estartit"),
          (barc_y.index[:], ((imfs_barcelona[1])[:])/10, 'brown', 'Barcelona'),
          (vale_y.index[:], ((imfs_valencia[1])[:])/10, 'yellow', 'Valencia'),
          (ali_y.index[:], ((imfs_alicante[1])[:])/10, 'violet', 'Alicante'),
          (mal_y.index[:], ((imfs_malaga[1])[:])/10, 'purple', 'Malaga'),
          (gib_y.index[:], ((imfs_gibraltar[1])[:])/10, 'gold', 'Gibraltar'),
          (alg_y.index[:], ((imfs_algeciras[1])[:])/10, 'darkred', 'Algeciras'),
          (tar_y.index[:], ((imfs_tarifa[1])[:])/10, 'darkblue', 'Tarifa'),
          (ceu_y.index[:], ((imfs_ceuta[1])[:])/10, 'turquoise', 'Ceuta'),
          (palma_y.index[:], ((imfs_palma[1])[:])/10, 'grey', 'Palma de Mallorca')
          ]

date_adria = ['1987','1991','1997','2006','2010','2017','2020']
date_ion = ['1987','1990','1998','2007','2010','2016','2020']
date_lev = ['1987','1992','1997','2007','2011','2016','2021']
date_aeg = ['1988','1993','1999','2007','2011','2017','2021']
date_west = ['1989','1993','1997','2006','2010','2016','2020']
date_med = ['1987','1992','1998','2007','2010','2017','2020']
all_date_bande = [date_adria, date_ion, date_lev, date_aeg, date_west, date_med]
all_series = [series1, series2, series3, series4, series5]
all_red_series = [adria_basin, ion_basin_combined, lev_basin, egeo_basin, western_med, med]
all_means = []
all_std_devs = []
for series_data in all_series:
    dfs = [pd.DataFrame(data, index=idx - pd.DateOffset(months=11)) for idx, data, _, _ in series_data]
    aligned_dfs = pd.concat(dfs, axis=1)
    mean_series = aligned_dfs.mean(axis=1)
    std_dev_series = aligned_dfs.std(axis=1)
    all_means.append(mean_series)
    all_std_devs.append(std_dev_series)
mediterranean_mean = pd.concat(all_means, axis=1).mean(axis=1)
mediterranean_std_dev = pd.concat(all_std_devs, axis=1).std(axis=1)
all_series.append(mediterranean_mean)

all_series = [('adria', all_series[0]),
                        ('ion', all_series[1]),
                        ('lev', all_series[2]),
                        ('aeg', all_series[3]),
                        ('west', all_series[4]),
                        ('med', all_series[5])]

def plot_on_axis(ax, name, series_data, red_series, date_bande, title, xlabel=True, ylabel=True, custom_mean_series=None, custom_std_dev_series=None):
    if isinstance(series_data, list):
        dfs = [pd.DataFrame(data, index=idx - pd.DateOffset(months=11)) for idx, data, _, _ in series_data]
        aligned_dfs = pd.concat(dfs, axis=1)
        mean_series = aligned_dfs.mean(axis=1)
        std_dev_series = aligned_dfs.std(axis=1)
    else:
        mean_series = series_data
        if custom_mean_series is not None and custom_std_dev_series is not None:
            std_dev_series = custom_std_dev_series
        else:
            std_dev_series = pd.Series(np.zeros_like(mean_series), index=mean_series.index)
    
    maxima_mean = argrelextrema(mean_series.values, np.greater, order = 1)[0]
    minima_mean = argrelextrema(mean_series.values, np.less, order = 1)[0]
    combined = sorted(list(maxima_mean) + list(minima_mean))
    combined = [0] + combined + [len(mean_series)-1]
    first_max = mean_series.index[maxima_mean[0]]
    first_min = mean_series.index[minima_mean[0]]
    if first_max < first_min:
        colors = ["#E69F00","#56B4E9"]
    else:
        colors = ["#56B4E9","#E69F00"]
    for i in range(len(combined)-1):
        start_idx = combined[i]
        end_idx = combined[i+1]
        ax.axvspan(mean_series.index[start_idx], mean_series.index[end_idx], color=colors[i % 2], alpha=0.3)
    for max_idx in maxima_mean:
        ax.axvspan(mean_series.index[max_idx] - timedelta(365.25/2),
                   mean_series.index[max_idx] + timedelta(365.25/2),
                   color='white', alpha=1)
    for min_idx in minima_mean:
        ax.axvspan(mean_series.index[min_idx] - timedelta(365.25/2),
                   mean_series.index[min_idx] + timedelta(365.25/2),
                   color='white', alpha=1)
    ax.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4)
    ax.plot(mean_series.index, mean_series, color='black', linewidth=2)
    if red_series is not None:
        ax.plot(red_series.index, red_series*100, linestyle='--', linewidth=3, color='red')
    for data in date_bande:
        year = int(float(data))
        month = int((float(data) - year) * 12 + 1)
        data_datetime = datetime(year, month, 1)
        ax.axvline(data_datetime, color='black', linestyle='--', linewidth=1.5)
    ax.set_xlim(datetime(1900, 1, 1), datetime(2022, 6, 30))
    ax.set_yticks(np.arange(int(min(ax.get_ylim())), int(max(ax.get_ylim()))+1, 2))
    if xlabel:
        ax.set_xlabel('time', fontsize=14)
    if ylabel:
        ax.set_ylabel('sea level (cm)', fontsize=14)
    ax.xaxis.set_major_locator(mdates.YearLocator(10))
    ax.xaxis.set_minor_locator(mdates.YearLocator(1))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
    ax.set_title(title, fontsize=14)
    ax.tick_params(axis='x', labelsize=12)
    ax.tick_params(axis='y', labelsize=12)
    
    return mean_series, std_dev_series

# 0 adriatic ; 1 Ionian ; 2 levantine ; 3 aegean ; 4 west ; 5 med
order = [5, 0, 4, 2, 3, 1]
ordered_series = [all_series[i] for i in order]
ordered_red_series = [all_red_series[i] for i in order]
ordered_date_bande = [all_date_bande[i] for i in order]

results = {}

fig, axes = plt.subplots(nrows=6, ncols=1, figsize=(14,11), dpi=100)
titles = ["Mediterranean", "Adriatic", "Western", "Levantine", "Aegean", "Ionian"]
axes = axes.flatten()
label_flags = [(True, False), (True, False), (True, False), (True, False), (True, False), (True, True)]
for ax, (name, series_data), red_series, date_bande, title, (ylabel, xlabel) in zip(axes, ordered_series, ordered_red_series, ordered_date_bande, titles, label_flags):
    if title == "Mediterranean":
        mean_series, std_dev_series = plot_on_axis(ax, name, series_data, red_series, date_bande, title, xlabel, ylabel, custom_mean_series=mediterranean_mean, custom_std_dev_series=mediterranean_std_dev)
    else:
        mean_series, std_dev_series = plot_on_axis(ax, name, series_data, red_series, date_bande, title, xlabel, ylabel)
    results[title] = {"mean": mean_series, "std_dev": std_dev_series}
plt.tight_layout()
plt.show()
df_results_grd = pd.concat({key: pd.DataFrame(val) for key, val in results.items()}, axis=1)


# - - - # - - - 


def dominant_periodicity(data):
    spectrum = np.fft.fft(data)
    frequencies = np.fft.fftfreq(len(data))
    freq = abs(frequencies[np.argmax(np.abs(spectrum[1:])) + 1])
    period = 1 / freq
    return period
groups = [series1, series2, series3, series4, series5]
group_names = ["Adriatic", "Ionian", "Levantine", "Aegean", "Western"]
total_periods = 0
num_groups = len(groups)
group_stds = []  
for idx, group in enumerate(groups):
    dominant_periods_group = [dominant_periodicity(data[1]) for data in group]
    group_mean = np.mean(dominant_periods_group)
    group_std = np.std(dominant_periods_group)
    group_stds.append(group_std)  
    total_periods += group_mean
    print(f"{group_names[idx]} average period: {group_mean:.1f} +/- {group_std:.1f}")
weighted_average = total_periods / num_groups
weighted_std = np.sqrt(np.sum(np.array(group_stds) ** 2) / num_groups)
print(f"Mediterranean weighted average period: {weighted_average:.1f} +/- {weighted_std:.1f}")


# DIFFERENCE BETWEEN GRD CORR AND NO_GRD CORR
#-----------------------------------------------------------------

df_difference = df_results_grd.sub(df_results)
df_difference = df_difference[df_difference.index < pd.Timestamp('2018-01-01')]


fig, axes = plt.subplots(nrows=6, ncols=1, figsize=(14,11), dpi=100)
titles = ["Mediterranean", "Adriatic", "Western", "Levantine", "Aegean", "Ionian"]
axes = axes.flatten()
for ax, title in zip(axes, titles):
    mean_series = df_difference[title]["mean"]
    std_dev_series = df_difference[title]["std_dev"]    
    ax.fill_between(mean_series.index, mean_series - std_dev_series, mean_series + std_dev_series, color='grey', alpha=0.4)
    ax.plot(mean_series.index, mean_series, color='black', linewidth=2)
    ax.set_xlim(datetime(1900, 1, 1), datetime(2018, 1, 31))
    ax.set_ylim(-4, 4)
    ax.set_yticks(np.arange(-4, 5, 2))
    ax.set_xlabel('time', fontsize=14)
    ax.set_ylabel('difference (cm)', fontsize=14)
    ax.xaxis.set_major_locator(mdates.YearLocator(10))
    ax.xaxis.set_minor_locator(mdates.YearLocator(1))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
    ax.set_title(title + " Difference", fontsize=14)
    ax.tick_params(axis='x', labelsize=12)
    ax.tick_params(axis='y', labelsize=12)
plt.tight_layout()
plt.show()

mean_values = df_difference.mean()
for col, mean_val in mean_values.items():
    print(f"Mean for serie {col}: {mean_val:.3f}")
#Mean for serie ('Mediterranean', 'mean'): -0.01 +- 0.2
#Mean for serie ('Mediterranean', 'std_dev'): 0.01
#Mean for serie ('Adriatic', 'mean'): 0.00 +- 0.18
#Mean for serie ('Adriatic', 'std_dev'): 0.07
#Mean for serie ('Western', 'mean'): -0.00 +- 0.18
#Mean for serie ('Western', 'std_dev'): 0.04
#Mean for serie ('Levantine', 'mean'): -0.15 +- 0.43
#Mean for serie ('Levantine', 'std_dev'): 0.07
#Mean for serie ('Aegean', 'mean'): -0.00 +- 0.13
#Mean for serie ('Aegean', 'std_dev'): -0.00
#Mean for serie ('Ionian', 'mean'): 0.10 +- 0.24
#Mean for serie ('Ionian', 'std_dev'): -0.06
sigma_values = df_difference[[col for col in df_difference.columns if col[1] == 'mean']].std()
#for (serie_name, _), sigma_val in sigma_values.iteritems():
#    print(f"1 sigma per la serie {serie_name}: {sigma_val:.2f}")









# EMD TOTAL COMPARISON --------------------------------------------------------
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

# No GRD series
series1_total_nogrd = [(tri_y2.index, imfs_trieste_nogrd/10),
          (ven_y2.index, imfs_venice_nogrd/10),
          (rav_y.index, imfs_ravenna_nogrd/10),
          (rov_y.index, imfs_rovinj_nogrd/10),
          (bak_y2.index, imfs_bakar_nogrd/10),
          (spl_y.index, imfs_split_nogrd/10),
          (dub_y.index, imfs_dubrovnik_nogrd/10),
          (rav_y_old.index, imfs_ravenna_old_nogrd/10),
          (zad_y.index, imfs_zadar_nogrd/10),
          (bar_y.index, imfs_bar_nogrd/10)
          ]
series2_total_nogrd = [(pre_y2.index, imfs_preveza_nogrd/10),
          (lev_y2.index, imfs_levkas_nogrd/10),
          (kat_y2.index, imfs_katakolon_nogrd/10),
          (val_y2.index, imfs_valletta_nogrd/10),
          (kal_y.index, imfs_kalamai_nogrd/10)
          ]
series3_total_nogrd = [(ant_y.index, imfs_antalya_nogrd/10),
          (ale_y.index, imfs_alexandria_nogrd/10),
          (had_y2.index, imfs_hadera_nogrd/10),
          (ant_y_new.index, imfs_antalya_new_nogrd/10),
          (said_y.index, imfs_portsaid_nogrd/10)
          ]
series4_total_nogrd = [(ler_y2.index, imfs_leros_nogrd/10),
          (khi_y.index, imfs_khios_nogrd/10),
          (alex_y2.index, imfs_alexandroupolis_nogrd/10),
          (the_y.index, imfs_thessaloniki_nogrd/10),
          (kha_y2.index, imfs_khalkis_nogrd/10),
          (pir_y2.index, imfs_piraievs_nogrd/10),
          (sir_y2.index, imfs_siros_nogrd/10),
          (bod_y.index, imfs_bodrum_nogrd/10),
          (izm_y.index, imfs_izmir_nogrd/10)
          ]
series5_total_nogrd = [(pal_y.index, imfs_palermo_nogrd/10),
          (nap_y.index, imfs_napoli_nogrd/10),
          (cag_y.index, imfs_cagliari_nogrd/10),
          (civ_y.index, imfs_civitavecchia_nogrd/10),
          (gen_y2.index, imfs_genova_nogrd/10),
          (mau_y.index, imfs_portomaurizio_nogrd/10),
          (tou_y2.index, imfs_toulon_nogrd/10),
          (mar_y2.index, imfs_marseille_nogrd/10),
          (sete_y2.index, imfs_sete_nogrd/10),
          (est_y2.index, imfs_estartit_nogrd/10),
          (barc_y2.index, imfs_barcelona_nogrd/10),
          (vale_y2.index, imfs_valencia_nogrd/10),
          (ali_y2.index, imfs_alicante_nogrd/10),
          (mal_y2.index, imfs_malaga_nogrd/10),
          (gib_y.index, imfs_gibraltar_nogrd/10),
          (alg_y.index, imfs_algeciras_nogrd/10),
          (tar_y2.index, imfs_tarifa_nogrd/10),
          (ceu_y.index, imfs_ceuta_nogrd/10),
          (palma_y2.index, imfs_palma_nogrd/10)
          ]

# GRD series
series1_total = [(tri_y.index, imfs_trieste/10),
          (ven_y.index, imfs_venice/10),
          (rav_y.index, imfs_ravenna/10),
          (rov_y.index, imfs_rovinj/10),
          (bak_y.index, imfs_bakar/10),
          (spl_y.index, imfs_split/10),
          (dub_y.index, imfs_dubrovnik/10),
          (rav_y_old.index, imfs_ravenna_old/10),
          (zad_y.index, imfs_zadar/10),
          (bar_y.index, imfs_bar/10)
          ]
series2_total = [(pre_y.index, imfs_preveza/10),
          (lev_y.index, imfs_levkas/10),
          (kat_y.index, imfs_katakolon/10),
          (val_y.index, imfs_valletta/10),
          (kal_y.index, imfs_kalamai/10)
          ]
series3_total = [(ant_y.index, imfs_antalya/10),
          (ale_y.index, imfs_alexandria/10),
          (had_y.index, imfs_hadera/10),
          (ant_y_new.index, imfs_antalya_new/10),
          (said_y.index, imfs_portsaid/10)
          ]
series4_total = [(ler_y.index, imfs_leros/10),
          (khi_y.index, imfs_khios/10),
          (alex_y.index, imfs_alexandroupolis/10),
          (the_y.index, imfs_thessaloniki/10),
          (kha_y.index, imfs_khalkis/10),
          (pir_y.index, imfs_piraievs/10),
          (sir_y.index, imfs_siros/10),
          (bod_y.index, imfs_bodrum/10),
          (izm_y.index, imfs_izmir/10)
          ]
series5_total = [(pal_y.index, imfs_palermo/10),
          (nap_y.index, imfs_napoli/10),
          (cag_y.index, imfs_cagliari/10),
          (civ_y.index, imfs_civitavecchia/10),
          (gen_y.index, imfs_genova/10),
          (mau_y.index, imfs_portomaurizio/10),
          (tou_y.index, imfs_toulon/10),
          (mar_y.index, imfs_marseille/10),
          (sete_y.index, imfs_sete/10),
          (est_y.index, imfs_estartit/10),
          (barc_y.index, imfs_barcelona/10),
          (vale_y.index, imfs_valencia/10),
          (ali_y.index, imfs_alicante/10),
          (mal_y.index, imfs_malaga/10),
          (gib_y.index, imfs_gibraltar/10),
          (alg_y.index, imfs_algeciras/10),
          (tar_y.index, imfs_tarifa/10),
          (ceu_y.index, imfs_ceuta/10),
          (palma_y.index, imfs_palma/10)
          ]

date_total = pd.date_range('1/1/1900','12/31/2022', freq='Y')
num_series = 3
num_values_per_series = 123
nan_array = np.empty((num_series, num_values_per_series))
nan_array[:] = np.nan

series1_total.insert(0, (date_total, nan_array))
series2_total.insert(0, (date_total, nan_array))
series3_total.insert(0, (date_total, nan_array))
series4_total.insert(0, (date_total, nan_array))
series5_total.insert(0, (date_total, nan_array))

series1_total_nogrd.insert(0, (date_total, nan_array))
series2_total_nogrd.insert(0, (date_total, nan_array))
series3_total_nogrd.insert(0, (date_total, nan_array))
series4_total_nogrd.insert(0, (date_total, nan_array))
series5_total_nogrd.insert(0, (date_total, nan_array))


# - - -  
groups = [series1_total, series2_total, series3_total, series4_total, series5_total]
groups_nogrd = [series1_total_nogrd, series2_total_nogrd, series3_total_nogrd, series4_total_nogrd, series5_total_nogrd]
dfs_list = []
dfs_list_nogrd = []
def process_series(series_container, dfs_list):
    for group in series_container:
        df = pd.DataFrame()
        for idx, (index, imfs) in enumerate(group):
            if len(imfs) > 1:
                imf_series = pd.Series(data=imfs[1], index=index)
                imf_series.index = imf_series.index - pd.DateOffset(months=11)
                df[f"serie_{idx}"] = imf_series
        dfs_list.append(df)
process_series(groups, dfs_list)
process_series(groups_nogrd, dfs_list_nogrd)
mean_curves = []
mean_curves_nogrd = []
for df, df_nogrd in zip(dfs_list, dfs_list_nogrd):
    mean_curves.append(df.mean(axis=1))
    mean_curves_nogrd.append(df_nogrd.mean(axis=1))
overall_mean = pd.concat(mean_curves, axis=1).mean(axis=1)
overall_sigma = pd.concat(mean_curves, axis=1).std(axis=1)
overall_mean_nogrd = pd.concat(mean_curves_nogrd, axis=1).mean(axis=1)
overall_sigma_nogrd = pd.concat(mean_curves_nogrd, axis=1).std(axis=1)

def calculate_normalized_rmse(series1, series2):
    rmse = np.sqrt(((series1 - series2) ** 2).mean())
    norm_rmse = rmse / (series1.max() - series1.min())
    return norm_rmse
norm_rmse_values = []
for mean_curve, mean_curve_nogrd in zip(mean_curves, mean_curves_nogrd):
    norm_rmse = calculate_normalized_rmse(mean_curve, mean_curve_nogrd)
    norm_rmse_values.append(norm_rmse)
overall_norm_rmse = calculate_normalized_rmse(overall_mean, overall_mean_nogrd)
norm_rmse_values.append(overall_norm_rmse)
print("Valori di NRMSE per ogni subplot:")
for idx, value in enumerate(norm_rmse_values):
    print(f"{idx + 1}: {value:.4f}")
#0.0331
#0.0605
#0.0875
#0.0260
#0.0566
#0.0563


fig, axs = plt.subplots(3, 2, figsize=(8, 4,), dpi=100) 
axs = axs.flatten() 
titles = ["Adriatic (3.3%)", "Ionian (6.1%)", "Levantine (8.8%)", "Aegean (2.6%)", "Western (5.7%)", "Mediterranean (5.6%)"]
for idx, (df, df_nogrd) in enumerate(zip(dfs_list, dfs_list_nogrd)):
    ax = axs[idx]
    mean_series = df.mean(axis=1)
    sigma = df.std(axis=1)
    mean_series_nogrd = df_nogrd.mean(axis=1)
    sigma_nogrd = df_nogrd.std(axis=1)
    ax.plot(mean_series_nogrd.index, mean_series_nogrd, 'black', linewidth=1.5)
    ax.fill_between(mean_series_nogrd.index, mean_series_nogrd - sigma_nogrd, mean_series_nogrd + sigma_nogrd, color='gray', alpha=0.4, edgecolor='none')
    ax.plot(mean_series.index, mean_series, 'red', linestyle=':', linewidth=3)
    ax.fill_between(mean_series.index, mean_series - sigma, mean_series + sigma, color='red', alpha=0.2, edgecolor='none')
    ax.axhline(y=0, color='black', linestyle='--', linewidth=0.5)
    ax.set_title(titles[idx])
    ax.set_xlim(pd.Timestamp('1900-01-1'), pd.Timestamp('2021-12-31'))
    ax.set_ylim(-4, 4)
    if idx in [0, 2, 4]:
        ax.set_ylabel("cm")
    ax.locator_params(axis='y', nbins=3)
    if idx < len(dfs_list) - 1: 
        ax.set_xticks([])
    if idx == 4 or idx == 5: 
        years = mdates.YearLocator(20)
        years_fmt = mdates.DateFormatter('%Y')
        ax.xaxis.set_major_locator(years)
        ax.xaxis.set_major_formatter(years_fmt)
ax = axs[5]
ax.plot(overall_mean_nogrd.index, overall_mean_nogrd, 'black', linewidth=1.5)
ax.fill_between(overall_mean_nogrd.index, overall_mean_nogrd - overall_sigma_nogrd, overall_mean_nogrd + overall_sigma_nogrd, color='gray', alpha=0.4, edgecolor='none')
ax.plot(overall_mean.index, overall_mean, 'red', linestyle=':', linewidth=3)
ax.fill_between(overall_mean.index, overall_mean - overall_sigma, overall_mean + overall_sigma, color='red', alpha=0.2, edgecolor='none')
ax.axhline(y=0, color='black', linestyle='--', linewidth=0.5)
ax.set_title(titles[5])
ax.set_xlim(pd.Timestamp('1900-01-01'), pd.Timestamp('2021-12-31'))
ax.set_ylim(-4, 4) 
ax.locator_params(axis='y', nbins=3)
plt.tight_layout()
plt.show()


# NAO PC-based (Hurrel 2003)
datenao = pd.date_range('1/1/1900','12/31/2022', freq='Y')
nao=pd.read_csv('path/nao.txt',\
                 delim_whitespace=True,header=None)[1:]
nao.index = datenao
nao = nao[1]
nao.index = nao.index - pd.DateOffset(months=11)

sea = nao.values
num_ensembles = 1
all_imfs = []
for _ in range(num_ensembles):
    eemd.noise_seed(np.random.randint(0, 1000))
    E_IMFs = eemd(sea)
    if E_IMFs.shape[0] == 6:
        E_IMFs[4] = (E_IMFs[4] + E_IMFs[5]) / 2
        E_IMFs = E_IMFs[:-1]
    all_imfs.append(E_IMFs)
min_imfs = min([len(imfs) for imfs in all_imfs])
imfs_sum = np.zeros((min_imfs, len(sea)))
for imfs in all_imfs:
    for i in range(min_imfs):
        imfs_sum[i] += imfs[i]
imfs_mean = imfs_sum / num_ensembles

plt.figure(figsize=(9,8), dpi=100)
plt.suptitle("NAO", y=0.83)
for n, imf in enumerate(imfs_mean):
    plt.subplot(len(imfs_mean)+1, 1, n+2)
    plt.plot(nao.index, imf, 'black')
    plt.ylabel("IMF %i" %(n+1))
    plt.ylim(imf.min(), imf.max())
    plt.locator_params(axis='y', nbins=2)
    if n+2 != len(imfs_mean)+1:
        plt.xticks([])
years = mdates.YearLocator(10)
years_minor = mdates.YearLocator(5)
years_fmt = mdates.DateFormatter('%Y')
plt.gca().xaxis.set_major_locator(years)
plt.gca().xaxis.set_major_formatter(years_fmt)
plt.gca().xaxis.set_minor_locator(years_minor)
if n+2 == len(imfs_mean)+1:
    plt.xlabel("Time")
plt.gca().tick_params(axis='x', which='minor', bottom=True, labelbottom=False)
plt.subplots_adjust(hspace=0)
plt.show()

#np.save('imfs_nao.npy', imfs_mean)
imfs_nao = np.load('path/imfs_nao.npy')

nao_2 = imfs_nao[1][:]
nao_3 = imfs_nao[2][:]
nao_ens = nao_2 + nao_3
nao_ens = pd.Series(data=nao_ens, index=nao.index)

plt.plot(nao_2)
plt.plot(nao_3)
plt.plot(nao_ens)


plt.figure(figsize=(7, 5), dpi=100)
ax1 = plt.gca()
ax1.plot(df_results.index, df_results['Mediterranean']['mean'], label='IMF 2 Adriatic', color='black', linewidth=1.5)
std_dev = df_results['Mediterranean']['std_dev']
mean = df_results['Mediterranean']['mean']
ax1.fill_between(df_results.index, mean-std_dev, mean+std_dev, color='gray', alpha=0.3, edgecolor=None)
ax1.set_xlabel('Time')
ax1.set_ylabel('sea level (cm)', color='black')
ax1.tick_params(axis='y', labelcolor='black')
ax2 = ax1.twinx()
ax2.plot(nao.index, nao_ens, label='IMF 2+3 NAO', color='red', linewidth=1)
ax2.set_ylabel('inverted NAO', color='red')
ax2.tick_params(axis='y', labelcolor='red')
ax2.invert_yaxis()
plt.show()


def dominant_periodicity(data):
    spectrum = np.fft.fft(data)    
    frequencies = np.fft.fftfreq(len(data))
    non_dc_component = np.argmax(np.abs(spectrum[1:])) + 1
    dominant_freq = abs(frequencies[non_dc_component])
    dominant_period = 1 / dominant_freq
    return dominant_period
def plot_fft_and_find_dominant(series, title):
    period = dominant_periodicity(series)
    fft_values = np.fft.fft(series)
    fft_freq = np.fft.fftfreq(len(series), d=1)
    periods = 1 / fft_freq[fft_freq > 0]
    amplitudes = np.abs(fft_values[fft_freq > 0])
    plt.figure(figsize=(10, 6))
    plt.plot(periods, amplitudes)
    plt.title(f'FFT Periods of {title}')
    plt.xlabel('Period (years)')
    plt.ylabel('Amplitude')
    plt.xlim(0, periods.max()) 
    plt.show()
    print(f"The dominant period for {title} is {period:.2f} years")

plot_fft_and_find_dominant(df_results['Adriatic']['mean'], "Adriatic Mean")
plot_fft_and_find_dominant(imfs_nao[1], "NAO")


nao_aligned = imfs_nao[2]
adriatic_aligned = df_results['Mediterranean']['mean']
ccf_full = np.correlate(nao_aligned - np.mean(nao_aligned), 
                        adriatic_aligned - np.mean(adriatic_aligned), mode='full')
n = len(nao_aligned)
lags_full = np.arange(-n + 1, n)
lag_limit = 26
ccf = ccf_full[n-1-lag_limit : n-1+lag_limit+1]
lags = lags_full[n-1-lag_limit : n-1+lag_limit+1]
ccf = ccf / (np.std(nao_aligned) * np.std(adriatic_aligned) * n)
conf_interval_99 = 2.58 / np.sqrt(2 * lag_limit + 1)
plt.figure(figsize=(10, 6))
plt.bar(lags, ccf, width=1.0, color='blue', edgecolor='black')
plt.axhline(y=conf_interval_99, linestyle='--', color='red', label='99% Confidence Interval')
plt.axhline(y=-conf_interval_99, linestyle='--', color='red')
plt.xlabel('Lag')
plt.ylabel('Cross-Correlation')
plt.title('Cross-Correlation between NAO and Adriatic Mean with 99% Confidence Interval')
plt.xlim(-lag_limit, lag_limit)
plt.legend()
plt.show()


from scipy import stats
slope, intercept, r_value, p_value, std_err = stats.linregress(nao_ens, df_results['Mediterranean']['mean'])
print(f"Coefficiente di regressione (cm/NAO unit): {slope}") # -0.67 c,m/NAO unit
print(f"Intercept: {intercept}")
print(f"R-squared: {r_value**2}")

from statsmodels.graphics.tsaplots import plot_acf
plt.figure(figsize=(12, 6))
plot_acf(df_results['Mediterranean']['mean'], lags=40, alpha=0.05)
plt.title('Autocorrelation Function (ACF)')
plt.xlabel('Lags')
plt.ylabel('Autocorrelation')
plt.show()

from scipy.stats import kendalltau
def effective_n(series, autocorr_lag1):
    n = len(series)
    return n / (1 + 2 * autocorr_lag1 * (n - 1) / n)
autocorr_lag1_nao = np.corrcoef(nao_ens[:-1], nao_ens[1:])[0, 1]
autocorr_lag1_med = np.corrcoef(df_results['Mediterranean']['mean'][:-1], df_results['Mediterranean']['mean'][1:])[0, 1]
n_eff1 = effective_n(nao_ens, autocorr_lag1_nao)
n_eff2 = effective_n(df_results['Mediterranean']['mean'], autocorr_lag1_med)
n_eff = min(n_eff1, n_eff2)
n_bootstrap = 10000
n_sample = int(n_eff)
tau_samples = []
p_values = []
for _ in range(n_bootstrap):
    sample_indices = np.random.choice(len(nao_ens), n_sample, replace=False)    
    tau, p_value = kendalltau(nao_ens.iloc[sample_indices], df_results['Mediterranean']['mean'].iloc[sample_indices])
    tau_samples.append(tau)
    p_values.append(p_value)
mean_tau = np.mean(tau_samples)
mean_p_value = np.mean(p_values)
print(f"Media di Kendall tau: {mean_tau}, Media dei p-value: {mean_p_value}")
# -0.27 ; p 0.03


fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 3.5), dpi=100)
ax1.axhline(y=0, color='black', linestyle='--', linewidth=0.5)
ax1.plot(df_results.index, df_results['Mediterranean']['mean'], color='black', linewidth=1.5)
std_dev = df_results['Mediterranean']['std_dev']
mean = df_results['Mediterranean']['mean']
ax1.fill_between(df_results.index, mean-std_dev, mean+std_dev, color='gray', alpha=0.3, edgecolor=None)
ax1.set_xlabel('Time', fontsize=12)
ax1.set_ylabel('IMF2 sea level (cm)', color='black', fontsize=12)
ax1.tick_params(axis='both', labelcolor='black', labelsize=10)
ax1_2 = ax1.twinx()
ax1_2.plot(nao.index, nao_ens-np.median(nao_ens), label='NAO IMF 2+3', color='red', linewidth=1)
ax1_2.set_ylabel('inverted NAO', fontsize=12, color='red', labelpad=10, rotation=270)
ax1_2.tick_params(axis='y', labelcolor='red', labelsize=10)
ax1_2.invert_yaxis()

ax2.bar(lags, ccf, width=1.0, color='black', edgecolor='white')
ax2.axhline(y=conf_interval_99, linestyle='--', color='red', label='99% CI')
ax2.axhline(y=-conf_interval_99, linestyle='--', color='red')
ax2.set_xlabel('Lag', fontsize=12)
ax2.set_ylabel('Cross-Correlation', fontsize=12, labelpad=10, rotation=270)
ax2.yaxis.set_label_position("right")
ax2.set_xlim(-lag_limit, lag_limit)
ax2.yaxis.tick_right()
ax2.tick_params(axis='both', labelcolor='black', labelsize=10)
plt.subplots_adjust(wspace=0.35)
plt.show()





