!
!  CHUONG TRINH thu nghiem hieu chinh KQ mo hinh Hybrid Statistical-Dynamical method 
!  Cac Mo hinh thong ke duoc su dung:
!  1) ANN: 
!  2) HQTT: Hoi quy tuyen tinh nhieu bien (Ket qua giong voi HQTB)
!  3) LAD: Least Absolute Deviation
!  4) LMV: Minimax
!  Cac nhan to du bao: Cac bien du bao cua mo hinh 

   PROGRAM BC_ANN 
   Use Netcdf

   Integer, Parameter :: Yr1=1982, Yr2=2011, Nmon=12, Nreg=7, NLead=5, Nvar=17, Nfile=9
   Integer, Parameter :: Nyrs=(Yr2-Yr1+1)
   Real, Parameter    :: Miss=-99.
   Character (Len=4)  :: vname(Nvar)=(/"pr_o","t2_o","tx_o","tm_o","pr","t2","tx","tm", &
                                       "h500","h850","olr","q2","rh2","slp","u200","u850","w700"/)
   Integer, Parameter :: Nvar_1=8
   Character (Len=4)  :: vname_1(Nvar_1)=(/"pr","t2","dh58","du28","olr","q2","rh2","w700"/)
   Integer, Parameter :: NLen=3
   Integer, Parameter :: TimeScale(NLen)=(/1,3,6/)
   Integer            :: Fcs_mon, Nyr1, NMax, Ncase, Ntc_var

   Character (Len=255) :: Fname
   Real, Allocatable   :: lon(:),lat(:),Regs(:,:), X3d(:,:,:)
! xlon,xlat,xlev,xtime,Nlo,Nla,Nz,Nt
   Real, Allocatable   :: xlon(:),xlat(:),xlev(:),xtime(:)
   Integer             :: Nlo,Nla,Nz,Nt 
   Integer             :: Nlon, Nlat, Ntime, Ngrd, ilon, ilat, it
   Integer             :: Mvars
   Real, Allocatable   :: Dat_All  (:,:,:,:,:) ! (Nlon,Nlat,Ntime,Nvar,NLead)
   Real, Allocatable   :: Dat_All_0(:,:,:,:,:) ! (Nlon,Nlat,Ntime,Nvar,NLead)
   Real, Allocatable   :: Dat_mean(:,:,:,:)  ! Dat_mean(Nlon,Nlat,Nmon,Nvar,NLead),Dat_std(Nlon,Nlat,Nmon,Nvar,NLead)
   Real, Allocatable   :: Dat_std (:,:,:,:) 
   Real, Allocatable   :: Del_Cli(:,:,:,:)   ! (Nlon,Nlat,NLead,Nmon) : Del = F - O
   Real, Allocatable   :: Bias_Cli(:,:,:,:)  ! (Nlon,Nlat,NLead,Nmon)    - Model Cli. Bias = Model_Fcs - Obs ==> Corrected=Model_Fcs-Bias
   Real, Allocatable   :: X_inp(:,:), Y_inp(:), Yest(:,:), Yhq(:,:)
   Character (Len=5)   :: yvarn, Model_nm
   !--------------------------------------------------------------------------------
   ! Drought IDXs:
   Real, Allocatable   :: Dr_M (:,:,:,:,:)  ! (Nlon,Nlat,Ntime,NLen,NLead) 
   Real, Allocatable   :: Dr_O (:,:,:,:,:)
   Real, Allocatable   :: Dr_ANN (:,:,:,:,:)

   Integer :: Nyear, imon      ! Tong so nam co SL va chi so thang
   !--------------------------------------------------------------------------------
   ! ANN:
   character (len=250) :: input_file, output_file, save_file
   character (len=250) :: Dir, Dir_ANN_Out, Dir_Cli, Dir_ANN_Save, Dir_Veri, Dir_4Dr
   logical :: training_mode

   ! Use for calculating scaling factors
   Integer :: Nsample, Nepoc, Nsample1

   Real,allocatable, Dimension(:,:) :: Inputs, Outputs, Inputs_X, Outputs_Y
   Real,allocatable, Dimension(:)   :: min_in, max_in, min_out, max_out
   Real :: mean_error, mean_error_check
   !-------------------------------------------------------------------------------
    integer ::  Nin, Nhidden, Nout, iin, ihid, iout
    integer :: i,j,k

    Real,allocatable, Dimension(:,:) :: weight_ih, weight_ho, moment_ih, moment_ho
    Real,allocatable, Dimension(:)   :: fin, fhid, fout, ftarget, delta_o, delta_h
   ! Training
    Real :: learning_rate0, learning_rate, momentum, error, tmp, mintmp
    logical :: debug, Run_Cli
   !--------------------------------------------------------------------------------
   Integer :: Op_Nhidden, Op_Nepoc   ! Optimal values
   Real    :: Op_learning_rate
   Real, Allocatable :: X4d(:,:,:,:), X5d(:,:,:,:), F1d(:),O1d(:) !, Score_Cor(:,:,:), Score_AV(:,:,:) 
   !------------------- For ANN -------------------------------------------------------------
   Namelist /ann_info/ Nhidden,learning_rate,momentum,training_mode,Nepoc,debug
   Namelist /Model_info/ Model_nm, yvarn

   !  Nhidden       =     5 !4        ! Number of hidden layers
   !  learning_rate =   0.01
   !  momentum      =  0.9 ! 10.0
   !  training_mode = .true.       ! For training
   !  Nepoc         =  1000        ! Iterative training times
   !  debug         = .false.
   !--------------------------------------------------------------------------------

   Open (1, file="Namelist_Dr_IDX.txt",Status="old")
   Read (1, ann_info)
   Read (1, Model_info)
   learning_rate0 = learning_rate

   Fname="/home/tanpv/Data/AWC/Mask_VN_0.25_Corrected.nc"
   Call rd_ncdf_2d (Fname,lon,lat,Nlon,Nlat,Regs,"reg") ! 7 sub-regs mask

   !Model_nm="clWRF";  yvarn="pr"

   Dir="/home/tanpv/Progs/562_VNU/Data/For_BC/"
   Call Read_all_data (Dir,Model_nm)
   !Call Calc_Dr_IDX
   Fname="/home/tanpv/Data/562_VNU/0.25_VN/Dr_IDXs/SPEI_obs1982-2021.nc"
   Call Read_Dr_IDX_Obs (Fname)

   Dir_ANN_Out ="/home/tanpv/Data/562_VNU/0.25_VN/ANN_Out/";
   Dir_ANN_Save="/home/tanpv/Data/562_VNU/0.25_VN/ANN_Save_grd/"
   Dir_Cli     ="/work/projects/G09/562_VNU/0.25_VN/Cli_Out/" !"/home/tanpv/Data/562_VNU/0.25_VN/Cli_Out/"
   Dir_4Dr     ="/home/tanpv/Data/562_VNU/0.25_VN/Dr_IDXs/"

   !--------------------------------------------------------------------------------
   ! Data stadardization:
   print*,"Beginning Data standardization..."
   Call Data_standardization
   Fname=trim(Dir_Cli)//"Mean_and_Std_4IDX_"//trim(Model_nm)//"_"//trim(yvarn)//".nc"
   Call Write_Mean_Std (Fname)
   !--------------------------------------------------------------------------------
   Nyear=Nyrs
   Allocate (Dr_ANN(Nlon,Nlat,Ntime,NLen,NLead))
   Do ilead=1,NLead
      Do ilon=1,Nlon
         Do ilat=1,Nlat
            if (Int(Regs(ilon,ilat))>0) then
               Do ilen=1,Nlen
                  Call Extract_Data (ilon,ilat,ilen,ilead)
                  write (save_file,"(4(A,I2.2),A)") trim(Dir_ANN_Save)//"Sav_"//trim(Model_nm)//"_lon_",ilon,"_lat_",ilat,"_len_",ilen,"_lead_",ilead,".txt"
                  learning_rate = learning_rate0 !  0.05
!print*,Nsample1,Mvars,learning_rate
                  Call ANN_2023(Inputs_X,Outputs_Y,Nsample1,Mvars,1,Miss)    
                  Dr_ANN(ilon,ilat,1:Ntime,ilen,ilead)=Yest(1:Ntime,1)
               Enddo
            endif
         Enddo
      Enddo
   Enddo
   write (Fname,"(A,I2.2,A)") trim(Dir_4Dr)//"SPEI_ANN_"//trim(Model_nm)//".nc"
   Call Write_Out_4_Drought (Fname)
   !--------------------------------------------------------------------------------
      
   CONTAINS
   !--------------------------------------------------------------------------------
   Subroutine Write_Out_4_Drought (Fname)
      ! Dr_ANN(Nlon,Nlat,Ntime,NLen,NLead)
      ! Dr_O  (ilon,ilat,it,ilen,ilead)
      Character (Len=*) :: Fname
      !Integer, parameter :: Nvar=4
      Character (Len=250) :: var_nm, t_unit, var_ln, var_unit, lon_nm, lat_nm, z_nm, t_nm, var_longname
      Integer :: imon,iyr,imem,ivar,it, Nz
      Real, Allocatable :: Y4d(:,:,:,:), zlev(:), xtime(:)
      !Character (Len=3), parameter :: vname(Nlen)=(/"obs","ann","mod","cli"/)
      !Character (Len=20), parameter :: v_ln(Nvar)=(/"observation","ANN estimation","Model Forecast","Climatology bias correction"/)
      ! X6d(Nlon,Nlat,Nmon,Nyear,Nmem+1,4)

      Nz=Nlead;
      Allocate (zlev(Nz),xtime(Ntime),Y4d(Nlon,Nlat,Nz,Ntime))
      Do i=1,Nz; zlev(i)=i; Enddo; 
      Do i=1,Ntime; xtime(i)=i; Enddo
      t_unit="months since 1982-01-01 "; lon_nm="lon"; lat_nm="lat"; t_nm="month"; z_nm="lead"
      Do ilen=1,Nlen
         write (var_ln,"(A,I1.1,A)") "Observed Drought index for timescale = ",ilen," month(s)"
         Do ilon=1,Nlon !it=1,Ntime 
            Do ilat=1,Nlat !ilon=1,Nlon
               Do ilead=1,Nlead
                  Y4d(ilon,ilat,ilead,1:Ntime)=Dr_O(ilon,ilat,1:Ntime,ilen,ilead)
               Enddo
            Enddo
         Enddo
         write (var_nm,"(A,I1.1)") "obs_",ilen
         if (ilen==1) then
            Call wr_ncdf_4d (Fname,Lon,Lat,zlev,xtime,Nlon,Nlat,Nz,Ntime,Y4d,trim(var_nm), &
                            t_unit, var_ln,"-",lon_nm, lat_nm, z_nm, t_nm, Miss) 
         else
            Call wr_ncdf_4d_apd (Fname,Y4d,trim(var_nm),Nlon,Nlat,Nz,Ntime, &
                             var_ln, "-", lon_nm, lat_nm, z_nm, t_nm, Miss)
         endif
      Enddo
      ! ANN:
      Do ilen=1,Nlen
         write (var_ln,"(A,I1.1,A)") "Corrected Drought index using variables of model outputs for timescale = ",ilen," month(s)"
         Do ilon=1,Nlon !it=1,Ntime 
            Do ilat=1,Nlat !ilon=1,Nlon
               Do ilead=1,Nlead
                  Y4d(ilon,ilat,ilead,1:Ntime)=Dr_ANN(ilon,ilat,1:Ntime,ilen,ilead)
               Enddo
            Enddo
         Enddo
         write (var_nm,"(A,I1.1)") "ann_",ilen
         Call wr_ncdf_4d_apd (Fname,Y4d,trim(var_nm),Nlon,Nlat,Nz,Ntime, &
                       var_ln, "-", lon_nm, lat_nm, z_nm, t_nm, Miss)
      Enddo 
   End Subroutine Write_Out_4_Drought
   !--------------------------------------------------------------------------------
   Subroutine Write_Mean_Std (Fname)
      Character (Len=*) :: Fname
      Character (Len=250) :: vname, t_unit, var_ln, var_unit, lon_nm, lat_nm, z_nm, t_nm
      Character (Len=2), Parameter :: mon(Nmon)=(/"01","02","03","04","05","06","07","08","09","10","11","12"/)
      Real, Allocatable, Dimension (:) :: zvar, xtime
      Real, Allocatable, Dimension (:,:,:,:) :: A4d 
      INteger :: imon,i, Nz, NLead2

      NLead2=NLead+2
      Allocate (zvar(Nvar_1),xtime(NLead2), A4d(Nlon,Nlat,Nvar_1,NLead2))
      Do i=1,Nvar_1; zvar(i)=i; Enddo; Do i=1,NLead2; xtime(i)=i; Enddo
      t_unit="months since 1982-01-01 "; lon_nm="lon"; lat_nm="lat"; t_nm="lead"; z_nm="var"

      var_ln="Mean values over entire baseline timeseris (1982-2011). Toal LT is 5, LT=6,7 are signed by LT=5" !. Month "//mon(imon)
      A4d(:,:,:,:)=Dat_mean(:,:,:,:); vname="mean" !//mon(imon)
      Call wr_ncdf_4d (Fname,Lon,Lat,zvar,xtime,Nlon,Nlat,Nvar_1,NLead2,A4d,trim(vname), &
                      t_unit, var_ln, "-", lon_nm, lat_nm, z_nm, t_nm, Miss)
      var_ln="Stadard deviation values over entire baseline timeseris (1982-2011). Toal LT is 5, LT=6,7 are signed by LT=5" !. Month "//mon(imon)
      A4d(:,:,:,:)=Dat_std(:,:,:,:); vname="std" !//mon(imon)
      Call wr_ncdf_4d_apd (Fname,A4d,trim(vname),Nlon,Nlat,Nvar_1,NLead2, &
                       var_ln, "-", lon_nm, lat_nm, z_nm, t_nm, Miss)
      Deallocate (zvar, xtime, A4d)
   End Subroutine Write_Mean_Std
   !--------------------------------------------------------------------------------
   Subroutine Extract_Data (ilon,ilat,ilen,ilead)
      Integer :: ireg,imon,imon1,ilon,ilat,ilen,ilead,ipredictand,iprd
      Integer :: it,Npoint,Mx,i,j,Nspl,iyr

      Nsample1=Ntime
      Mx=8                 ! So bien doc lap
      Mvars=Mx
      if (Allocated(X_inp)) Deallocate (X_inp)
      if (Allocated(Y_inp)) Deallocate (Y_inp)
      Allocate (X_inp(Nsample1,Mx),Y_inp(Nsample1))
      Do it=1,Ntime
         Y_inp(it)  =Dr_O (ilon,ilat,it,ilen,ilead)   ! Observation
         X_inp(it,1)=Dat_All_0(ilon,ilat,it,1,ilead)  ! pr
         X_inp(it,2)=Dat_All_0(ilon,ilat,it,2,ilead)  ! t2
         X_inp(it,3)=Dat_All_0(ilon,ilat,it,3,ilead)  ! dh58=h500-h850
         X_inp(it,4)=Dat_All_0(ilon,ilat,it,4,ilead)  ! du28=u200-u850
         X_inp(it,5)=Dat_All_0(ilon,ilat,it,5,ilead)  ! olr
         X_inp(it,6)=Dat_All_0(ilon,ilat,it,6,ilead)  ! q2
         X_inp(it,7)=Dat_All_0(ilon,ilat,it,7,ilead)  ! rh2
         X_inp(it,8)=Dat_All_0(ilon,ilat,it,8,ilead)  ! w700
!print"(i5,10F8.3)",it,Y_inp(it),X_inp(it,:); if (mod(it,30)==0) pause
         ! 4 neighbor gridpoints
     !    X_inp(it,8)=Dat_All_0(ilon-1,ilat,it,1,ilead)          ! dh58=h500-h850 
     !    X_inp(it,9)=Dat_All_0(ilon+1,ilat,it,1,ilead)          ! 
     !    X_inp(it,10)=Dat_All_0(ilon,ilat-1,it,1,ilead)         !
     !    X_inp(it,11)=Dat_All_0(ilon,ilat+1,it,1,ilead)         ! 

     !    X_inp(it,12)=Dat_All_0(ilon-1,ilat,it,2,ilead)   ! du28=u200-u850
     !    X_inp(it,13)=Dat_All_0(ilon+1,ilat,it,2,ilead)   ! 
     !    X_inp(it,14)=Dat_All_0(ilon,ilat-1,it,2,ilead)   ! 
     !    X_inp(it,15)=Dat_All_0(ilon,ilat+1,it,2,ilead)   ! 

     !    X_inp(it,16)=Dat_All_0(ilon-1,ilat,it,6,ilead)   ! w700
     !    X_inp(it,17)=Dat_All_0(ilon+1,ilat,it,6,ilead)   ! w700
     !    X_inp(it,18)=Dat_All_0(ilon,ilat-1,it,6,ilead)   ! w700
     !    X_inp(it,19)=Dat_All_0(ilon,ilat+1,it,6,ilead)   ! w700
      Enddo
      if (Allocated(Inputs_X)) Deallocate (Inputs_X)
      if (Allocated(Outputs_Y)) Deallocate (Outputs_Y)
      Allocate (Inputs_X(Mx,Nsample1), Outputs_Y(1,Nsample1))
      !i=0
      Do it=1,Nsample1
         Outputs_Y(1,it)=Y_inp(it)
         Do j=1,Mx
            Inputs_X(j,it)=X_inp(it,j)
         Enddo
      Enddo
   End Subroutine Extract_Data
   !--------------------------------------------------------------------------------
   Subroutine Read_all_data (Dir,Model_nm)
      Character (Len=*) :: Dir,Model_nm
      Character (Len=255) :: Fname
      Real, Allocatable :: xlon(:),xlat(:),xtime(:)
      Integer :: ilead,ivar,Nlo,Nla,Nt

      Do ilead=1,NLead
         write(Fname,"(A,I1.1,A)") trim(Dir)//"lead",ilead,"_"//trim(Model_nm)//"_VN.nc"  ! clWRF_VN.nc"
         Do ivar=1,Nvar
            Call rd_ncdf_3d (Fname,xlon,xlat,xtime,Nlo,Nla,Nt,X3d,trim(vname(ivar)))
            if (ilead==1.AND.ivar==1) then
               Ntime=Nyrs*Nmon ! Ntime=Nt
               Allocate (Dat_All(Nlon,Nlat,Ntime,Nvar,NLead))
               Dat_All=Miss
            endif
            Dat_All(:,:,1:Nt,ivar,ilead) = X3d(:,:,1:Nt)
            Deallocate (xlon,xlat,xtime,X3d)
         Enddo
      Enddo
   End Subroutine Read_all_data
   !--------------------------------------------------------------------------------
   Subroutine Read_Dr_IDX_Obs (Fname)
      Character (Len=*) :: Fname
      Integer :: ilen,ilon,ilat,imon,imon1,ilead,it,i,ivar
      Integer :: Nlo,Nla,Nle,Nt
      Real, Allocatable :: X4d(:,:,:,:),xlon(:),xlat(:),xtime(:),xlen(:)

      Call rd_ncdf_4d (Fname,xlon,xlat,xlen,xtime,nlo,nla,nle,nt,X4d,"idx")
      if (Allocated (Dr_O)) Deallocate (Dr_O)
      Allocate (Dr_O(Nlon,Nlat,Ntime,NLen,NLead))
      Do ilead=1,Nlead
         Do ilen=1,Nlen
            Do it=1,Ntime
               Dr_O(:,:,it,ilen,ilead)=X4d(:,:,ilen,it)
            Enddo
         Enddo
      Enddo
   End Subroutine Read_Dr_IDX_Obs
   !--------------------------------------------------------------------------------
   Subroutine Calc_Dr_IDX
      Integer :: ilen,ilon,ilat,imon,imon1,ilead,it,i,ivar, Nlead2
      Real, Dimension (Ntime) :: Temp, Rain, DrIDX
      Real :: Latitude
      !   Real, Allocatable   :: Dr_M (:,:,:,:,:)  ! (Nlon,Nlat,Ntime,NLen,NLead) 
      !   Real, Allocatable   :: Dr_O (:,:,:,:,:)

      print*, "Calculating Drought Index:"
      Allocate (Dr_O(Nlon,Nlat,Ntime,NLen,NLead),Dr_M(Nlon,Nlat,Ntime,NLen,NLead))
      Do ilead=1,Nlead
         Do ilon=1,Nlon
            Do ilat=1,Nlat
               Latitude=Lat(ilat)
               Temp(1:Ntime)=Dat_All(ilon,ilat,1:Ntime,2,ilead)   ! "t2_o"
               Rain(1:Ntime)=Dat_All(ilon,ilat,1:Ntime,1,ilead)   ! "pr_o"
               Do ilen=1,Nlen
                  Call Calc_SPEI_One_Stn (Temp,Rain,Latitude,Ntime,Nmon,TimeScale(ilen),DrIDX,Miss)
                  Dr_O(ilon,ilat,1:Ntime,ilen,ilead)=DrIDX(1:Ntime)
               Enddo

               Temp(1:Ntime)=Dat_All(ilon,ilat,1:Ntime,6,ilead)   ! "t2"
               Rain(1:Ntime)=Dat_All(ilon,ilat,1:Ntime,5,ilead)   ! "pr"
               Do ilen=1,Nlen
                  Call Calc_SPEI_One_Stn (Temp,Rain,Latitude,Ntime,Nmon,TimeScale(ilen),DrIDX,Miss)
                  Dr_M(ilon,ilat,1:Ntime,ilen,ilead)=DrIDX(1:Ntime)
               Enddo
!print*,ilead,ilon,ilat
            Enddo
         Enddo
      Enddo
   End Subroutine Calc_Dr_IDX
   !--------------------------------------------------------------------------------
   Subroutine Data_standardization
      Integer :: ilon,ilat,imon,imon1,ilead,it,i,ivar, Nlead2
      Real    :: X1d(Ntime),xmean,std,tmp,MaxX, MinX, a, b
      Real, Allocatable :: Dat_tmp(:,:,:,:,:)
      !Real, Dimension (Ntime) :: Temp, Rain, DrIDX

      ! vname_1(Nvar_1)=(/"dh58","du28","olr","q2","rh2","w700"/)
      ! vname(Nvar)=(/"pr_o","t2_o","tx_o","tm_o","pr","t2","tx","tm", &
      !                 1       2     3       4     5    6    7    8
      !                                 "h500","h850","olr","q2","rh2","slp","u200","u850","w700"/)
      !                                    9      10    11   12    13    14     15     16     17
      Allocate (Dat_tmp(Nlon,Nlat,Ntime,Nvar_1,NLead))
      Dat_tmp=Miss
      Do ilon=1,Nlon
         Do ilat=1,Nlat
            Do ilead=1,Nlead
!print*,ilead,ilon,ilat
               Do it=1,Ntime
                  Dat_tmp(ilon,ilat,it,1,ilead) = Dat_All(ilon,ilat,it,5,ilead)          ! 1: pr
                  Dat_tmp(ilon,ilat,it,2,ilead) = Dat_All(ilon,ilat,it,6,ilead)          ! 2: t2
                  a = Dat_All(ilon,ilat,it,9,ilead); b = Dat_All(ilon,ilat,it,10,ilead)  !    h500 & h850
                  if (a/=Miss.AND.b/=Miss) Dat_tmp(ilon,ilat,it,3,ilead) = (a-b) !/100.           ! 3: h500-h850
                  a = Dat_All(ilon,ilat,it,15,ilead); b = Dat_All(ilon,ilat,it,16,ilead) !    u200 & u850
                  if (a/=Miss.AND.b/=Miss) Dat_tmp(ilon,ilat,it,4,ilead) = a-b           ! 4: u200-u850
                  Dat_tmp(ilon,ilat,it,5,ilead) = Dat_All(ilon,ilat,it,11,ilead)         ! 5: olr
                  Dat_tmp(ilon,ilat,it,6,ilead) = Dat_All(ilon,ilat,it,12,ilead) !*10000.         ! 6: q2
                  Dat_tmp(ilon,ilat,it,7,ilead) = Dat_All(ilon,ilat,it,13,ilead)         ! 7: rh2
                  Dat_tmp(ilon,ilat,it,8,ilead) = Dat_All(ilon,ilat,it,17,ilead)         ! 8: w700
               Enddo
            Enddo
         Enddo
      Enddo 

      print*,"Data standardization..."
      Nlead2=Nlead+2     ! Lead=6,7 <-- Lead=5
      Allocate (Dat_mean(Nlon,Nlat,Nvar_1,NLead2),Dat_std(Nlon,Nlat,Nvar_1,NLead2))
      Allocate (Dat_All_0(Nlon,Nlat,Ntime,Nvar_1,NLead))    ! Stadardized data
      Dat_All_0=Miss

      Do ilon=1,Nlon
         Do ilat=1,Nlat
            Do ivar=1,Nvar_1
               Do ilead=1,Nlead

                  X1d(1:Ntime)=Dat_tmp(ilon,ilat,1:Ntime,ivar,ilead)

                 ! xmean=Ave(X1d,Ntime,Miss); std=Stdev(X1d,Ntime,Miss)
                 ! Dat_mean(ilon,ilat,ivar,ilead)=xmean
                 ! Dat_std (ilon,ilat,ivar,ilead)=std
                  MaxX=Xmax(X1d,Ntime,Miss); MinX=Xmin(X1d,Ntime,Miss)
                  Dat_mean(ilon,ilat,ivar,ilead)=MaxX       ! x'=(x-xmin)/(xmax-xmin)=>(x-std)/(mean-std)
                  Dat_std (ilon,ilat,ivar,ilead)=MinX
!if (MaxX/=Miss.AND.MinX/=Miss) then !.AND.MaxX/=MinX) then
!   print"(A,4I3,2F20.5)","ilon,ilat,ivar,ilead: ",ilon,ilat,ivar,ilead,MaxX,MinX 
!endif
                  Do it=1,Ntime
                     !imon1=mod(it,Nmon); if (imon1==0) imon1=Nmon
                     !if (imon1==imon) then
                     tmp = Dat_tmp(ilon,ilat,it,ivar,ilead)           ! Unstandadized data
                     if (tmp/=Miss) then
                     !if (tmp/=Miss.AND.xmean/=Miss.AND.std/=Miss.AND.std/=0) then  ! standadized
                   !  if (tmp/=Miss.AND.xmean/=Miss) then                           ! Anomaly only
                        !Dat_All_0(ilon,ilat,it,ivar,ilead)=(tmp-xmean) !/std
                        Dat_All_0(ilon,ilat,it,ivar,ilead)=(tmp-MinX)/(MaxX-MinX)
                     endif
                   !  Dat_All_0(ilon,ilat,it,ivar,ilead)=tmp        ! Do nothings
                     !endif
                  Enddo
               Enddo
               Dat_mean(ilon,ilat,ivar,Nlead+1)=Dat_mean(ilon,ilat,ivar,Nlead)
               Dat_std (ilon,ilat,ivar,Nlead+1)=Dat_std (ilon,ilat,ivar,Nlead)
               Dat_mean(ilon,ilat,ivar,Nlead+2)=Dat_mean(ilon,ilat,ivar,Nlead)
               Dat_std (ilon,ilat,ivar,Nlead+2)=Dat_std (ilon,ilat,ivar,Nlead)
            Enddo
         Enddo
      Enddo
      Deallocate (Dat_tmp)
   End Subroutine Data_standardization
   !--------------------------------------------------------------------------------
     
   !Include "/home/tanpv/Mylibs/Sub_HQTT.f90"
   !Include "/home/tanpv/Mylibs/Sub_LAD.f90"
   !Include "/home/tanpv/Mylibs/Sub_LMV.f90"
   Include "/home/tanpv/Mylibs/Calc_Correlation_Coefficient.f90"  ! Correlation (X, Y, N, Corr, Prob, Miss)
   Include "/home/tanpv/Mylibs/Sub_Verification.f90"              ! ME, MAE, RME, RMAE
   Include "/home/tanpv/Mylibs/sub_wr_ncdf_Tan.F90" 
   Include "/home/tanpv/Mylibs/sub_rd_ncdf_Tan.F90"
   Include "/home/tanpv/Mylibs/Sub_neural_2023.f90"
   Include "/home/tanpv/Mylibs/Stdev.f90"
   Include "/home/tanpv/Mylibs/Ave.f90"
   Include "/home/tanpv/Mylibs/Xmax.f90"
   Include "/home/tanpv/Mylibs/Xmin.f90"
   Include "/home/tanpv/Mylibs/Sub_SPEI_One_Stn_2023.f90"
   !--------------------------------------------------------------------------------
   END
   Include "/home/tanpv/Mylibs/Student_Prob.f90"
   !-------------------------------------------------------------------------------------------
