#!/usr/bin/env python3
"""Scatter plot visualization module for observational data."""

import sqlite3
import datetime
from statistics import median
from typing import List, Optional, Tuple

import numpy as np
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.colorbar as cbar
import matplotlib.cm as cm
import matplotlib.colors as colors
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.ticker import FuncFormatter
from mpl_toolkits.axes_grid1 import make_axes_locatable
import cartopy.feature

import pikobs
def projectPpoly(proj, lat, lon, deltax, deltay, src_crs):
    """Transform polygon corners from lat/lon to projection coordinates."""
    points = []
    for dlon, dlat in [(-deltax, -deltay), (-deltax, deltay), (deltax, deltay), (deltax, -deltay)]:
        x, y = proj.transform_point(lon + dlon, lat + dlat, src_crs)
        points.append([x, y])
    return points
def surface_area_lat_lon(lat1, lat2, lon1, lon2):
    """Calculate surface area in km² for a lat/lon rectangle.
    
    Formula: (π/180)R² |sin(lat2)-sin(lat1)| |lon2-lon1|
    Uses numpy arrays for vectorized computation.
    """
    R = 6371.0  # Earth radius in km
    lat2 = np.minimum(lat2, 90.0)
    surf = (R**2 * (np.pi / 180.0) * 
            np.abs(np.sin(lat2 * np.pi / 180.0) - np.sin(lat1 * np.pi / 180.0)) * 
            np.abs(lon2 - lon1))
    return surf
def days_between(d1, d2):
    """Calculate days between two dates in format YYYYMMDDHH."""
    d1_dt = datetime.datetime.strptime(d1, "%Y%m%d%H")
    d2_dt = datetime.datetime.strptime(d2, "%Y%m%d%H")
    delta = d2_dt - d1_dt
    return delta.total_seconds() / (24 * 3600)

def round_first_digit_3(x):
    """Format number with adaptive decimal places based on magnitude."""
    if x == 0:
        return "0"
    abs_x = abs(x)
    if abs_x >= 10:
        return f"{int(x)}"
    elif abs_x >= 0.1:
        return f"{round(x, 2)}"
    else:
        mantissa, exp = f"{x:.1e}".split("e")
        mantissa = mantissa.split(".")[0]
        return f"{mantissa}e{int(exp)}"

WIND_TYPE_MAPPING = {
    1: "Wind derived from cloud motion observed in the infrared channel",
    2: "Wind derived from cloud motion observed in the visible channel",
    3: "Wind derived from cloud motion observed in the water vapour channel",
    4: "Wind derived from motion observed in a combination of spectral channels",
    5: "Wind derived from motion observed in the water vapour channel in clear air",
    6: "Wind derived from motion observed in the ozone channel",
    7: "Wind derived from motion observed in water vapour channel (cloud or clear air not specified)",
}


def _build_where_clause(id_stn: str, vcoord: str) -> str:
    """Build SQL WHERE clause based on id_stn and vcoord parameters.
    
    Args:
        id_stn (str): Station ID ('join', 'all', or specific ID)
        vcoord (str): Vertical coordinate ('join' or specific value)
    
    Returns:
        str: WHERE clause fragment
    """
    if id_stn == 'join' and vcoord == 'join':
        return ""
    elif id_stn == 'join' and vcoord != 'join':
        return f" and vcoord = {vcoord}"
    elif id_stn != 'join' and vcoord == 'join':
        return f" and id_stn = '{id_stn}'"
    else:  # Both id_stn and vcoord are specific
        return f" and vcoord = {vcoord} and id_stn = '{id_stn}'"


def wind_type(code_or_codes):
    """Get wind type description(s) for given code(s)."""
    def map_one(c):
        try:
            return WIND_TYPE_MAPPING.get(int(c), f"Unknown code {c}")
        except (ValueError, TypeError):
            return f"Unknown code {c}"

    if isinstance(code_or_codes, (list, tuple, set)):
        return [map_one(c) for c in code_or_codes]

    try:
        import pandas as pd
        if isinstance(code_or_codes, pd.Series):
            return code_or_codes.map(map_one)
    except ImportError:
        pass

    return map_one(code_or_codes)
def scatter_plot(
    mode: str,
    region: str,
    family: str,
    id_stn: str,
    datestart: str,
    dateend: str,
    Points: str,
    boxsizex: float,
    boxsizey: float,
    proj: str,
    pathwork: str,
    flag_criteria: str,
    fonction: str,
    vcoord: str,
    filesin: List[str],
    namesin: List[str],
    varno: int,
    intervales: Tuple,
    condition_sw: Optional[int] = None
) -> None:

    selected_flags = pikobs.flag_criteria(flag_criteria)

    vartyp=fonction
   
    # ========== Initialize parameters ==========
    pointsize = 0.5
    deltay = float(boxsizey) / 2.0
    deltax = float(boxsizex) / 2.0

    # ========== Parse interval parameters ==========
    interval_a = intervales[0]
    interval_b = intervales[1]
    if interval_a is None and interval_b is None:
        criteria_interval = ''
        layers = 'layer_all'
    else:
        criteria_interval = f' and {interval_a*100} <= vcoord <= {interval_b*100}'
        layers = f'Layer: {interval_a} hPa - {interval_b} hPa'

    # ========== Setup database connection ==========
    conn = sqlite3.connect(":memory:")
    cursor = conn.cursor()
    cursor.execute("PRAGMA TEMP_STORE=memory")
    cursor.execute(f"ATTACH DATABASE '{filesin[0]}' AS db1")

    FNAM, FNAMP, SUM, SUM2 = pikobs.type_boxes(fonction)

    # ========== Build WHERE clause based on id_stn and vcoord ==========
    where_clause = _build_where_clause(id_stn, vcoord)



    # ========== Setup database table names and wind condition filter ==========
    if len(filesin) > 1:
        create_table = 'boites1'
        info_name = f"{namesin[0]} VS {namesin[1]}"
    else:
        create_table = 'AVG'
        info_name = namesin[0]

    criteria_wind = ''
    name_wind_suffix = ''
    layer_wind_desc = ''
    if condition_sw is not None:
        criteria_wind = f' and WIND_COMP_METHOD={condition_sw}'
        name_wind_suffix = f'_OBS_SWMT_{condition_sw}_'
        layer_wind_desc = wind_type(condition_sw)

    query = f"""CREATE TEMPORARY TABLE {create_table} AS
                   SELECT boite, 
                          lat,
                          lon, 
                          varno, 
                          vcoord,
                          SUM({SUM})/SUM(CAST(N AS FLOAT)) AVG,
                          SQRT(SUM({SUM2})/SUM(CAST(N AS FLOAT)) - SUM({SUM})/SUM(CAST(N AS FLOAT))*SUM({SUM})/SUM(CAST(N AS FLOAT))) STD,
                          SUM(sumstat)/SUM(CAST(N AS FLOAT)) BCORR,
                          SUM(n) N
                   FROM db1.moyenne
                   where varno={varno}
                   {where_clause}
                   {criteria_wind}
                   GROUP BY boite, lat, lon, varno having sum(n)>3;"""
    cursor.execute(query)

    if len(filesin) > 1:
        cursor.execute(f"ATTACH DATABASE '{filesin[1]}' AS db2")
        query = f"""CREATE TEMPORARY TABLE boites2 AS
                   SELECT boite, lat, lon, varno, vcoord,
                          SUM({SUM})/SUM(CAST(N AS FLOAT)) AVG,
                          SQRT(SUM({SUM2})/SUM(CAST(N AS FLOAT)) - SUM({SUM})/SUM(CAST(N AS FLOAT))*SUM({SUM})/SUM(CAST(N AS FLOAT))) STD,
                          SUM(sumstat)/SUM(CAST(N AS FLOAT)) BCORR,
                          SUM(n) N
                   FROM db2.moyenne
                   where varno={varno}
                   {where_clause}
                   {criteria_wind}
                   GROUP BY boite, lat, lon, varno having sum(n)>3;"""
        cursor.execute(query)

        query = """Create temporary table AVG as
                   SELECT BOITES1.boite BOITE,
                          BOITES1.lat LAT,
                          BOITES1.lon LON,
                          BOITES1.vcoord VCOORD,
                          BOITES1.varno VARNO,
                          ABS(BOITES1.avg) - ABS(BOITES2.avg) AVG,
                          COALESCE(ABS(BOITES1.avg), 8888) AVG1,
                          COALESCE(ABS(BOITES2.avg), 8888) AVG2,
                          ABS(BOITES1.std) - ABS(BOITES2.std) STD,
                          COALESCE(ABS(BOITES1.std), 8888) as std1,
                          COALESCE(ABS(BOITES2.std), 8888) as std2,
                          ABS(BOITES1.bcorr) - ABS(BOITES2.bcorr) BCORR,
                          COALESCE(ABS(BOITES1.bcorr), 8888) AS bcorr1,
                          COALESCE(ABS(BOITES2.bcorr), 8888) AS bcorr2,
                          BOITES1.N - BOITES2.N N,
                          COALESCE(BOITES1.N, 8888) AS N1,
                          COALESCE(BOITES2.N, 8888) AS N2
                   FROM BOITES1, BOITES2
                   WHERE BOITES1.boite = BOITES2.boite AND BOITES1.VCOORD = BOITES2.VCOORD;"""
        cursor.execute(query)
       
    # ========== Fetch results from database ==========
    if len(filesin) > 1:
        query = """SELECT lat, lon, avg, std, N, N1, N2, avg1, avg2, std1, std2, bcorr, bcorr1, bcorr2
                   FROM AVG;"""
    else:
        query = """SELECT lat, lon, avg, std, BCORR, N
                   FROM AVG;"""

    cursor.execute(query)
    results = cursor.fetchall()

    # ========== Convert results to numpy arrays ==========
    lat = np.array([row[0] for row in results])
    lon = np.array([row[1] for row in results])
    avg = np.array([row[2] for row in results])
    std = np.array([row[3] for row in results])
    bcorr = np.array([row[4] for row in results])
    nombre = np.array([row[5] for row in results])

    resultados = []  # Initialize for use later
    if len(filesin) > 1:
        N1 = np.array([row[5] for row in results])
        N2 = np.array([row[6] for row in results])
        avg1 = np.array([row[7] for row in results])
        avg2 = np.array([row[8] for row in results])
        std1 = np.array([row[9] for row in results])
        std2 = np.array([row[10] for row in results])
        bcorr = np.array([row[11] for row in results])
        bcorr1 = np.array([row[12] for row in results])
        bcorr2 = np.array([row[13] for row in results])

        # Fetch boxes that exist only in one dataset
        sql = """SELECT b1.boite, b1.lat, b1.lon
                  FROM boites1 b1
                  LEFT JOIN boites2 b2 ON b1.boite = b2.boite
                  WHERE b2.boite IS NULL
                  UNION
                  SELECT b2.boite, b2.lat, b2.lon
                  FROM boites2 b2
                  LEFT JOIN boites1 b1 ON b2.boite = b1.boite
                  WHERE b1.boite IS NULL"""
        cursor.execute(sql)
        resultados = cursor.fetchall()
        
    # ========== Calculate density and remove None values ==========
    dens = nombre / surface_area_lat_lon(lat - deltay, lat + deltay, lon - deltax, lon + deltax)

    index_none = np.where(avg == None)
    lat = np.delete(lat, index_none)
    lon = np.delete(lon, index_none)
    avg = np.delete(avg, index_none)
    std = np.delete(std, index_none)
    bcorr = np.delete(bcorr, index_none)
    nombre = np.delete(nombre, index_none)

    query = f"""SELECT
               '{datestart}' AS date_start,
               '{dateend}' AS date_end,
               '{family}' AS family,
               '{varno}' AS varno,
               avg(avg) AS avg,
               avg(std) AS std,
               sum(N) AS N
            FROM AVG;"""
       
    cursor.execute(query)
    results = cursor.fetchall()
    date_start = np.array([row[0] for row in results])
    date_end = np.array([row[1] for row in results])
    family_array = np.array([row[2] for row in results])
    Mu = np.array([row[4] for row in results])
    Sigma = np.array([row[5] for row in results])
    Nobs = np.array([row[6] for row in results])

    conn.close()
    plot_type = ''
       
    if Sigma[0] is not None:
           Sigma = np.round(Sigma, 3)
           plot_type = fonction
           PERIODE = f'From {datestart} To {dateend}'
           NDAYS = max(1/4, days_between(datestart, dateend))
           variable_name, units, vcoord_type = pikobs.type_varno(varno)
       
           if vcoord == 'join':
               Nomvar = f"{variable_name} {units} \n id_stn:{id_stn} vcoord/channel:{(vcoord)} {layers} \n {layer_sw}"
           else:
               Nomvar = f"{variable_name} {units} \n id_stn:{id_stn} vcoord/channel:{int(vcoord)} {layers} "
       
           mode = 'MOYENNE'
       
           plt.close('all')
           fig = plt.figure(figsize=(10, 10))
           plt.rcParams['axes.linewidth'] = 1
           fontsize = 17
       
           Ninterv = 10
       
           if vartyp == 'dens' or vartyp == 'dens%' :
               OMP = dens / NDAYS 
               if len(filesin) > 1:
                  den1 = N1/surface_area_lat_lon(lat-deltay,lat+deltay,lon-deltax,lon + deltax) 
                  den2 = N2/surface_area_lat_lon(lat-deltay,lat+deltay,lon-deltax,lon + deltax) 
                  OMP = (den2-den1)*100/den1  

                  vmin = -100
                  vmax =  100
               else:
                     vmin = np.min(OMP)
                     vmax = np.max(OMP)
               cmap_base = cm.get_cmap('PuRd', lut=Ninterv)
               if vmin < 0:
                   max_abs = max(abs(vmin), abs(vmax))
                   vmin, vmax = -max_abs, max_abs
           elif vartyp in ['nobs', 'NOBSHDR']:
               Ninterv = 10
               OMP = nombre / NDAYS
               if len(filesin) > 1:
                   N1=N1 / NDAYS
                   N2=N2/ NDAYS

                   OMP =(N2-N1)*100/N1
                   vmin = -100
                   vmax = 100
               else:
                  vmin = np.min(OMP)
                  vmax = np.max(OMP)

               max_abs = max(abs(vmin), abs(vmax))
               if vmin > 0.0:
                   Ninterv = 11
                   cmap_base = cm.get_cmap('PuRd', lut=Ninterv)
                   vmin, vmax = vmin + 1, vmax
               else:
                   cmap_base = cm.get_cmap('RdYlBu_r', lut=Ninterv)
                   vmin, vmax = -max_abs, max_abs
           elif vartyp == 'obs':
               if len(filesin) > 1:
                   OMP =(abs(avg2)-abs(avg1))*100/abs(avg1)
                   vmin = -100
                   vmax= 100

               else:
                  OMP = avg
                  vmin = np.min(OMP)
                  vmax = np.max(OMP)
                  cmap_base = cm.get_cmap('RdYlBu_r', lut=Ninterv)  
           elif vartyp == 'bcorr':
               if len(filesin) > 1:
                   with np.errstate(divide='ignore', invalid='ignore'):
                      OMP =(abs(bcorr2)-abs(bcorr1))*100/abs(bcorr1)
                   vmin = -100
                   vmax= 100

               else:
                  OMP = bcorr
                  vmin = np.min(OMP)
                  vmax = np.max(OMP)
                  cmap_base = cm.get_cmap('RdYlBu_r', lut=Ninterv)

           elif vartyp in ['omp', 'oma', 'bcorr', 'stdomp', 'stdoma']:
               N = 10
               if len(filesin) > 1:
                   if vartyp  in ['omp', 'oma'] : 
                       with np.errstate(divide='ignore', invalid='ignore'):
                         OMP =(abs(avg2)-abs(avg1))*100/abs(avg1)
                       vmin = -100
                       vmax = 100
                   if vartyp in  ['stdomp', 'stdoma'] :
                    
                       OMP =(abs(std2)-abs(std1))*100/abs(std1) 
                   
               else:
                   if vartyp  in ['omp', 'oma'] : 
                       OMP = avg

                       vmax = np.max(np.abs(OMP))
                       vmin = -vmax
                       

                       cmap_base = cm.get_cmap('seismic', lut=N)


                   if vartyp == 'stdomp':
                       OMP = std
                       mode = 'SIGMA'
                       typer = 'STD'
                       vmin = np.min(OMP)
                       vmax = np.max(OMP)
                       cmap_base = cm.get_cmap('PuRd', lut=Ninterv)

               cmap_base = cm.get_cmap('RdYlBu_r', lut=Ninterv)
       
           if len(filesin) > 1:
             extend_color = 'both'
             vmin=-100
             vmax=100
             boundaries = np.array(
                 list(range(vmin, -5, 20)) +   # Negative values down to -5
                 [-5, 5] +                      # White range [-5, 5]
                 list(range(20, vmax+10, 20))   # Positive values from 20
             )          
             y = boundaries


             # Negative colors
             neg_colors = [cm.RdYlBu_r(x) for x in np.linspace(0.08, 0.40, len(boundaries[boundaries < -2]))]
             
             # White color for [-5,5]
             blanco = (1.0, 1.0, 1.0, 1.0)
             
             # Positive colors
             pos_colors = [cm.RdYlBu_r(x) for x in np.linspace(0.60, 0.92, len(boundaries[boundaries > 2]))]
             
             # Concatenar colores
             colores = neg_colors + [blanco] + pos_colors
             
             # Crear cmap y norm
             cmap = colors.ListedColormap(colores)
             cmap.set_under('#0235ad')
             cmap.set_over('#b30000')
             norm = colors.BoundaryNorm(boundaries, cmap.N)
             
             # Ticks para el colorbar
             ticks = list(boundaries[boundaries < -5]) + [-5, 5] + list(boundaries[boundaries > 5])

           else:

               boundaries = np.linspace(vmin, vmax, Ninterv + 1)
               y = boundaries[:-1] + (boundaries[1] - boundaries[0]) / 2
               cmap = cmap_base
               norm = cm.colors.Normalize(vmin=vmin, vmax=vmax)
               extend_color = None
               ticks = boundaries
               #Colors = [m.to_rgba(x) for x in y]

           m = cm.ScalarMappable(norm=norm, cmap=cmap)
           Colors = [m.to_rgba(x) for x in y]
           inds = np.digitize(OMP, boundaries) - 1
           inds = np.clip(inds, 0, len(Colors) - 1)
       
           nombres = 0
           left, bottom = 0.90, 0.15
           ax, fig, LATPOS, PROJ, pc = pikobs.type_projection(proj)
           ONMAP = 0 
           ONMAP2 = 0
           POINTS = 'OFF'
           patch_list = []

           for i in range(len(nombre)):
               x1, y1 = PROJ.transform_point(lon[i], lat[i], pc)
               point = PROJ.transform_point(lon[i], lat[i], src_crs=pc)
               fig_coords = ax.transData.transform(point)
               ax_coords = ax.transAxes.inverted().transform(fig_coords)
               xx, yy = ax_coords
               mask = (xx >= -0.01) & (xx <= 1.01) & (yy >= -0.01) & (yy <= 1.01)
               if mask:
                   ONMAP += nombre[i]
                   if len(filesin) > 1:
 
                       ONMAP2 +=N1[i]
                   if POINTS == 'ON':
                       plt.text(point[0], point[1], int(np.floor(nombre[i])), color="k", fontsize=17, zorder=5, ha='center', va='center', weight='bold')
                   else: 
                       if boxsizex >=10:
                          plt.text(point[0], point[1], round_first_digit_3(OMP[i]), color="b", fontsize=5, zorder=5, ha='center', va='center', weight='bold')
                     
                       points4 = projectPpoly(PROJ, lat[i], lon[i], deltax, deltay, pc)
                       
                       valor = OMP[i]

                       if valor < -100:
                           col =  '#0235ad' #67001f' #0235ad'   #67001f #053061     
                       elif valor > 100:
                           col = '#b30000' #e600c7' #b2182b' #e600c7'         
                       else:
                           ind = np.digitize(valor, boundaries) - 1
                           col = Colors[inds[i]]     
                       if len(filesin) == 1:

                           col = Colors[inds[i]]

                       
                       poly = plt.Polygon(points4, fc=col, zorder=4, ec='k', lw=0.2, alpha=1.0)
                       ax.add_patch(poly)
           if len(filesin) > 1:
            
            for boite, latn, lonn in resultados:
             points4 = projectPpoly(PROJ, latn, lonn, deltax, deltay, pc)

             poly = plt.Polygon(points4, fc=(0,0,0,1), zorder=4, ec='k', lw=0.8, alpha=1.0)
             ax.add_patch(poly)


       
           ax.coastlines()
           ax.add_feature(cartopy.feature.LAND, zorder=1, edgecolor='#C0C0C0', facecolor='#C0C0C0')
           ax.add_feature(cartopy.feature.OCEAN, zorder=0, edgecolor='#7f7f7f', facecolor='#00bce3')
           ax.add_feature(cartopy.feature.BORDERS, zorder=10)
           ax.add_feature(cartopy.feature.COASTLINE, zorder=10)
           gl = ax.gridlines(color='b', linestyle=(0, (1, 1)), xlocs=range(-180, 190, 10), ylocs=LATPOS, draw_labels=False, zorder=0)
       
           divider = make_axes_locatable(ax)
           ax3 = divider.append_axes("right", size="5%", pad=0.05, axes_class=plt.Axes)
       
           cb2 = cbar.ColorbarBase(
               ax3, cmap=cmap,
               norm=norm,
               orientation='vertical',
               drawedges=True,
               extend= extend_color,
               ticks=ticks,
               boundaries=boundaries,
               alpha=1.0
           )
           def scientific(x, pos):
               return f'{x:.1e}'
       
           if vartyp == 'dens' :
               if len(filesin) < 1:
                    cb2.ax.yaxis.set_major_formatter(FuncFormatter(scientific))
       
           dif = ''
           if len(filesin) > 1:
               dif = 'Differences'
           if len(filesin) > 1 and   vartyp == 'dens':
                cb2.ax.set_ylabel(f'Percentage of increase in sum(dens [nobs/km²])/days \n relative to {namesin[0]} [%]', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) > 1 and  vartyp == 'nobs':
                cb2.ax.set_ylabel(f'Percentage of increase in sum(nobs)/days \n relative to {namesin[0]} [%]', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) > 1 and   vartyp == 'omp': 
                cb2.ax.set_ylabel(f'Percentage of improvement in OMP \n relative to {namesin[0]} [%]', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) > 1 and  vartyp == 'oma' :
                cb2.ax.set_ylabel(f'Percentage of improvement in OMA \n relative to {namesin[0]} [%]', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) > 1 and   vartyp == 'obs' :
                cb2.ax.set_ylabel(f'Percentage of improvement in {variable_name}  \n relative to {namesin[0]} [%]', fontsize=15, rotation=90, labelpad=20)
           if len(filesin) > 1 and   vartyp == 'bcorr' :
                cb2.ax.set_ylabel(f'Percentage increase in bcorr \n relative to {namesin[0]} [%]', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) > 1 and   vartyp == 'stdomp' :
                cb2.ax.set_ylabel(f'Percentage increase in stdomp \n relative to {namesin[0]} [%]', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) > 1 and   vartyp == 'stdoma' :
                cb2.ax.set_ylabel(f'Percentage increase in stdoma \n relative to {namesin[0]} [%]', fontsize=18, rotation=90, labelpad=20)
           


           if len(filesin) == 1 and   vartyp == 'dens':
                cb2.ax.set_ylabel(f'sum(dens [nobs/km²])/days', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) == 1 and  vartyp == 'nobs':
                cb2.ax.set_ylabel(f'sum(nobs)/days', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) == 1 and   vartyp == 'omp': 
                cb2.ax.set_ylabel(f'OMP {units}', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) == 1 and  vartyp == 'oma' :
                cb2.ax.set_ylabel(f'OMA {units}', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) == 1 and   vartyp == 'obs' :
                cb2.ax.set_ylabel(f'{variable_name}  {units}', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) == 1 and   vartyp == 'bcorr' :
                cb2.ax.set_ylabel(f' BIAS Correction {units} ', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) == 1 and   vartyp == 'stdomp' :
                cb2.ax.set_ylabel(f' STDOMP Correction {units} ', fontsize=18, rotation=90, labelpad=20)
           if len(filesin) == 1 and   vartyp == 'stdoma' :
                cb2.ax.set_ylabel(f' STDOMA Correction {units} ', fontsize=18, rotation=90, labelpad=20)

           if len(filesin) < 1:
               fontsize = 12
               ax.text(0.00, 1.05, namesin[0], fontsize=fontsize, color='b', transform=ax.transAxes) 
          
           else: 
               fontsize = 12
               start_x = 0.00
               y_coord = 1.05
               text1_len = len(namesin[0]) * 1.5
               text1_x = start_x
       
               if len(filesin) > 1:
                   text2_len = len(namesin[1])
                   text2_x = text1_x + text1_len
                   text3_x = text1_x + 0.2
                   ax.text(text1_x, y_coord, 'Diff ' + namesin[0] , fontsize=fontsize, color='blue', transform=ax.transAxes)
                   ax.text(text3_x, y_coord, "-" + namesin[1] , fontsize=fontsize, color='red', transform=ax.transAxes)
               else:
                   ax.text(text1_x, y_coord,  namesin[0] , fontsize=fontsize, color='blue', transform=ax.transAxes)
       
           ax.text(0.00 + 20, 1.05, vartyp, fontsize=fontsize, color='k', transform=ax.transAxes)
           ax.text(0.00, 1.02, PERIODE, fontsize=fontsize, color='#3366FF', transform=ax.transAxes)
           ax.text(0.35, 1.05, Nomvar, fontsize=fontsize, color='k', transform=ax.transAxes, fontweight='bold')
       
           ax.text(0.5, -0.08, 'Longitude', transform=ax.transAxes, ha='center', va='top', fontsize=14)
           ax.text(-0.06, 0.5, 'Latitude', transform=ax.transAxes, ha='center', va='bottom', rotation='vertical', fontsize=14)
       
           props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
           if vartyp in [f'dens', 'nobs']:
               textstr = f'Nobs=%.2i (for %.2f days)' % (ONMAP, NDAYS)
           else:
               textstr = '$\\bar{\\mu}=%.3f$ $\\bar{\\sigma}=%.3f$ \nNobs=%.2i (for %.2f days)' % (Mu, Sigma, ONMAP, NDAYS)
       
           if len(filesin) < 2:
               ax.text(0.85, 1.17, textstr, transform=ax.transAxes, fontsize=fontsize, verticalalignment='top', bbox=props)
           else:
               textstr = f'Diff Nobs={ONMAP:02d} \nDiff%={((ONMAP/(ONMAP2*NDAYS))*100):.2f}% for {NDAYS:.2f} days'
               ax.text(0.88, 1.15, textstr, transform=ax.transAxes, fontsize=fontsize, verticalalignment='top', bbox=props)
        
           plt.grid(True)
           plt.rcParams['axes.linewidth'] = 2
       
           if vcoord == 'join':
               plt.savefig(f'{pathwork}/{family}/{fonction}_{proj}_{layers}_id_stn_{id_stn}_{region}_vcoord_{vcoord}_varno{varno}{name_wind_suffix}.png', dpi=600, format='png')
           else:
               plt.savefig(f'{pathwork}/{family}/{fonction}_{proj}_{layers}_id_stn_{id_stn}_{region}_vcoord_{int(vcoord)}_varno{varno}{name_wind_suffix}.png', dpi=600, format='png')
           plt.close(fig) 
       
