!
   PROGRAM Verify_QM 
   Use Netcdf

   Integer, Parameter :: Yr1=1982, Yr2=2011, Nmon=12, Nreg=7, NLead=5, Nvar=4, Nfile=9
   Integer, Parameter :: Nyrs=(Yr2-Yr1+1)
   Real, Parameter    :: Miss=-99.
   Character (Len=3)  :: vname (Nvar)=(/"obs","mod","bjp","q_m"/)
   Character (Len=3)  :: vname0(Nvar)=(/"obs","bjp","q_m","mod"/)

   Character (Len=255) :: Fname
   Real, Allocatable   :: lon(:),lat(:),Regs(:,:), X3d(:,:,:)

   Real, Allocatable   :: xlon(:),xlat(:),xlev(:),xtime(:)
   Integer             :: Nlo,Nla,Nz,Nt 
   Integer             :: Nlon, Nlat, Ntime, Ngrd, ilon, ilat, it
   Integer             :: Nmodel,Nele 
   Real, Allocatable   :: Dat_All(:,:,:,:,:) ! (Nlon,Nlat,Ntime,Nvar,NLead)
   Real, Allocatable   :: X_inp(:,:), Y_inp(:), Yest(:,:), Yhq(:,:)
   Character (Len=5),Allocatable   :: yvarn(:), Model_nm(:)

   !--------------------------------------------------------------------------------
   ! Verification:

   Real, Allocatable, Dimension(:,:,:,:,:) :: Pr_ME, Pr_MAE, Pr_RME, Pr_RMAE, Pr_COR, Pr_Pval, Pr_AV  ! (Nlon,Nlat,Nmon,NLead,Nvar)

   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
   character (len=250) :: Dir_QM, Dir_BJP
   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, iele, imod

    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 /Model_info_1/ Nmodel, Nele
   Namelist /Model_info_2/ Model_nm, yvarn

   !--------------------------------------------------------------------------------

   Open (1, file="Namelist.txt",Status="old")
   Read (1, Model_info_1)
   Allocate (yvarn(Nele), Model_nm(Nmodel))
   Read (1, Model_info_2)

   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

   Nyear=Nyrs
   Nvar1=Nvar-1       ! model, bjp, q_m

   Allocate (Pr_RME(Nlon,Nlat,NLead,Nmon,Nvar1),Pr_RMAE(Nlon,Nlat,NLead,Nmon,Nvar1),Pr_COR(Nlon,Nlat,NLead,Nmon,Nvar1),Pr_Pval(Nlon,Nlat,NLead,Nmon,Nvar1))
   Allocate (Pr_ME (Nlon,Nlat,NLead,Nmon,Nvar1),Pr_MAE (Nlon,Nlat,NLead,Nmon,Nvar1),Pr_AV (Nlon,Nlat,NLead,Nmon,Nvar1))
   Pr_ME=Miss; Pr_MAE=Miss; Pr_RME=Miss; Pr_RMAE=Miss; Pr_COR=Miss; Pr_Pval=Miss; Pr_AV=Miss
   Allocate (Score_Cor(Nreg,Nmon,NLead,Nvar1), Score_AV(Nreg,Nmon,NLead,Nvar1))   ! Number of gridpoints with Cor>0, AV>0

   Dir_Veri    ="/home/tanpv/Data/562_VNU/0.25_VN/Verify/"
   !Dir_QM      ="/home/tanpv/Data/562_VNU/0.25_VN/QM_Ha/"//"/"//trim(yvarn(iele))//"/"//"Baseline/"
   Dir_BJP     ="/home/tanpv/Data/562_VNU/0.25_VN/BJP/"

   !--------------------------------------------------------------------------------
   Do iele=1,Nele
      Do imod=1,Nmodel
         Dir_QM="/home/tanpv/Data/562_VNU/0.25_VN/QM_Ha/"//trim(yvarn(iele))//"/"//"Baseline/"
         Call Read_all_data (Dir_BJP,Dir_QM,Model_nm(imod),yvarn(iele))
       !  pause
         print*,"Deading data done for ",Model_nm(imod),yvarn(iele)
         !--------------------------------------------------------------------------------
         Call Verification

         Fname=trim(Dir_Veri)//"Veri_Training_BMJ_QM_"//trim(yvarn(iele))//"_"//trim(Model_nm(imod))//".nc" 
         Call Write_Verification (Fname,yvarn(iele),Model_nm(imod))

         Open (3,file=trim(Dir_Veri)//"Score_Cor_AV_Training_"//trim(yvarn(iele))//"_"//trim(Model_nm(imod))//".txt",status="Unknown") 
         Do ivar=1,Nvar1
            write (3,"(A)") "Percentage of grid points with positive correlation and added value of "//trim(vname0(ivar+1))
            Do ilead=1,NLead
               write (3,"(A,I1.1,A)") "Lead time = ",ilead," month(s)"
               write (3,"(6x,A6,12I6)") " Reg. ",(imon, imon=1,Nmon)
               Do ireg=1,Nreg
                  write (3,"(A6,I6,12F6.1)") "Cor - ",ireg,(Score_Cor(ireg,imon,ilead,ivar),imon=1,Nmon)
                  write (3,"(2A6,12F6.1)") "AV -  "," ",(Score_AV (ireg,imon,ilead,ivar),imon=1,Nmon)
               Enddo
            Enddo
         Enddo
         Close (3)
      Enddo
   Enddo
   !--------------------------------------------------------------------------------
      
   CONTAINS
   !--------------------------------------------------------------------------------
   Subroutine Verification !(ilead,imon)
      Integer :: ilon,ilat,imon,imon1,ilead,ireg, ic, ic0, ic1, ic2, it
      Integer, Parameter :: N=Nyrs !-1
      Real :: obs(N),bjp(N),model(N),q_m(N),Corr,Prob
     
      Do ilead=1,NLead
         Do ilon=1,Nlon
            Do ilat=1,Nlat
               if (Int(Regs(ilon,ilat))>0) then
                  Do imon=1,Nmon
                     ic=0
                     Do it=1,Ntime
                        imon1=mod(it,Nmon); if (imon1==0) imon1=Nmon
                        if (imon1==imon) then
                           ic=ic+1
                           obs(ic)  =Dat_All(ilon,ilat,it,1,ilead); model(ic)=Dat_All(ilon,ilat,it,2,ilead)
                           bjp(ic)  =Dat_All(ilon,ilat,it,3,ilead); q_m(ic)=Dat_All(ilon,ilat,it,4,ilead)
                        endif
                     Enddo
                     if (ic>N) then; print*,"Something's wrong in Verification"; stop; endif
                     Pr_ME  (ilon,ilat,ilead,imon,1) = ME  (bjp,  obs,ic,Miss)
                     Pr_ME  (ilon,ilat,ilead,imon,3) = ME  (model,obs,ic,Miss)
                     Pr_ME  (ilon,ilat,ilead,imon,2) = ME  (q_m,  obs,ic,Miss)
 
                     Pr_MAE (ilon,ilat,ilead,imon,1) = MAE (bjp,  obs,ic,Miss)
                     Pr_MAE (ilon,ilat,ilead,imon,3) = MAE (model,obs,ic,Miss)
                     Pr_MAE (ilon,ilat,ilead,imon,2) = MAE (q_m,  obs,ic,Miss)

                     Pr_RME (ilon,ilat,ilead,imon,1) = RME_1 (bjp,  obs,ic,Miss)
                     Pr_RME (ilon,ilat,ilead,imon,3) = RME_1 (model,obs,ic,Miss)
                     Pr_RME (ilon,ilat,ilead,imon,2) = RME_1 (q_m,  obs,ic,Miss)

                     Pr_RMAE(ilon,ilat,ilead,imon,1) = RMAE_1(bjp,  obs,ic,Miss)
                     Pr_RMAE(ilon,ilat,ilead,imon,3) = RMAE_1(model,obs,ic,Miss)
                     Pr_RMAE(ilon,ilat,ilead,imon,2) = RMAE_1(q_m,  obs,ic,Miss)

                     Call Correlation (bjp,  obs,ic,Corr,Prob,Miss); Pr_COR(ilon,ilat,ilead,imon,1)=Corr; Pr_Pval(ilon,ilat,ilead,imon,1)=Prob
                     Call Correlation (model,obs,ic,Corr,Prob,Miss); Pr_COR(ilon,ilat,ilead,imon,3)=Corr; Pr_Pval(ilon,ilat,ilead,imon,3)=Prob
                     Call Correlation (q_m,  obs,ic,Corr,Prob,Miss); Pr_COR(ilon,ilat,ilead,imon,2)=Corr; Pr_Pval(ilon,ilat,ilead,imon,2)=Prob

                     Pr_AV (ilon,ilat,ilead,imon,1) = AV (bjp,model,obs,ic,Miss)  ! Added value of bjp vs model
                     Pr_AV (ilon,ilat,ilead,imon,2) = AV (q_m,model,obs,ic,Miss)  ! Added value of q_m vs model
                     Pr_AV (ilon,ilat,ilead,imon,3) = Miss                        ! Not use
                  Enddo
               endif
            Enddo
         Enddo
      Enddo 
      !
      Do ivar=1,Nvar1
         Do ilead=1,NLead
            Do imon=1,Nmon
               Do ireg=1,Nreg
                  ic0=0; ic1=0; ic2=0
                  Do ilon=1,Nlon
                     Do ilat=1,Nlat
                        if (Int(Regs(ilon,ilat))==ireg) then
                           ic0=ic0+1
                           if (Pr_COR (ilon,ilat,ilead,imon,ivar)>0.0) ic1=ic1+1
                           if (Pr_AV  (ilon,ilat,ilead,imon,ivar)>0.0) ic2=ic2+1
                        endif
                     Enddo
                  Enddo
                  Score_Cor(ireg,imon,ilead,ivar)=real(ic1)/real(ic0)*100.0
                  if (ivar<Nvar1) then
                     Score_AV(ireg,imon,ilead,ivar)=real(ic2)/real(ic0)*100.0
                  else
                     Score_AV(ireg,imon,ilead,ivar)=Miss !ivar)=Miss
                  endif
               Enddo
            Enddo
         Enddo
      Enddo
   End Subroutine Verification
   !--------------------------------------------------------------------------------
   Subroutine Write_Verification (Fname,yvname,model_nm)
      Character (Len=*) :: Fname,yvname,model_nm
      Character (len=3), parameter :: vname(Nvar-1)=(/"bjp","q_m","mod"/)
      Character (Len=150) :: var_nm, t_unit, var_ln, var_unit, lon_nm, lat_nm, z_nm, t_nm
      Real, Allocatable, Dimension (:) :: zlev, xtime
      INteger :: i, Nvar1

      Nvar1=Nvar-1
      Allocate (zlev(NLead),xtime(Nmon))
      Do i=1,NLead; zlev(i)=i; Enddo; Do i=1,Nmon; xtime(i)=i; Enddo
      t_unit="months since 1982-01-01 "; var_unit="-"
      lon_nm="lon"; lat_nm="lat"; t_nm="mon"; z_nm="lead"

      if (Allocated(X4d)) Deallocate (X4d)
      Allocate (X4d(Nlon,Nlat,NLead,Nmon))
      Do ivar=1,Nvar1
         X4d(:,:,:,:)=Pr_RME(:,:,:,:,ivar)
         var_ln="Relative Mean Errors (RME) for "//trim(model_nm)
         var_nm="rme_"//trim(vname(ivar))
         if (ivar==1) then
            Call wr_ncdf_4d (Fname,Lon,Lat,zlev,xtime,Nlon,Nlat,NLead,Nmon,X4d,var_nm, &
                            t_unit, var_ln, "-", lon_nm, lat_nm, z_nm, t_nm, Miss)
         else
            Call wr_ncdf_4d_apd (Fname,X4d,var_nm,Nlon,Nlat,NLead,Nmon, &
                                var_ln,var_unit, lon_nm, lat_nm, z_nm, t_nm,Miss) 
         endif

         X4d(:,:,:,:)=Pr_RMAE(:,:,:,:,ivar)
         var_ln="Relative Mean Absolute Errors (RMAE) for"//trim(model_nm)
         var_nm="rmae_"//trim(vname(ivar))
         Call wr_ncdf_4d_apd (Fname,X4d,var_nm,Nlon,Nlat,NLead,Nmon, &
                                var_ln,var_unit, lon_nm, lat_nm, z_nm, t_nm,Miss)

         X4d(:,:,:,:)=Pr_ME(:,:,:,:,ivar)
         var_ln="Mean Errors (ME) for "//trim(model_nm)
         var_nm="me_"//trim(vname(ivar))
         Call wr_ncdf_4d_apd (Fname,X4d,var_nm,Nlon,Nlat,NLead,Nmon, &
                                var_ln,var_unit, lon_nm, lat_nm, z_nm, t_nm,Miss)

         X4d(:,:,:,:)=Pr_MAE(:,:,:,:,ivar)
         var_ln="Mean Absolute Errors (MAE) for "//trim(model_nm)
         var_nm="mae_"//trim(vname(ivar))
         Call wr_ncdf_4d_apd (Fname,X4d,var_nm,Nlon,Nlat,NLead,Nmon, &
                                var_ln,var_unit, lon_nm, lat_nm, z_nm, t_nm,Miss)

         X4d(:,:,:,:)=Pr_COR(:,:,:,:,ivar)
         var_ln="Correlation between "//trim(vname(ivar))//" and observation for "//trim(model_nm)
         var_nm="cor_"//trim(vname(ivar))
         Call wr_ncdf_4d_apd (Fname,X4d,var_nm,Nlon,Nlat,NLead,Nmon, &
                                var_ln,var_unit, lon_nm, lat_nm, z_nm, t_nm,Miss)

         X4d(:,:,:,:)=Pr_Pval(:,:,:,:,ivar)
         var_ln="p-values of Correlation between "//trim(vname(ivar))//" and observation for "//trim(model_nm)
         var_nm="pv_"//trim(vname(ivar))
         Call wr_ncdf_4d_apd (Fname,X4d,var_nm,Nlon,Nlat,NLead,Nmon, &
                                var_ln,var_unit, lon_nm, lat_nm, z_nm, t_nm,Miss)

         X4d(:,:,:,:)=Pr_AV(:,:,:,:,ivar)
         if (ivar==1) then
            var_ln="Added values of ANN bias correction compared to model output for "//trim(model_nm)
            var_nm="av_bjp"
         else if (ivar==2) then
            var_ln="Added values of Cli bias correction compared to model output for "//trim(model_nm)
            var_nm="av_q_m"
         else
            var_ln="No AV more. All values are filled by Missing for "//trim(model_nm)
            var_nm="av_undef"
         endif
         Call wr_ncdf_4d_apd (Fname,X4d,var_nm,Nlon,Nlat,NLead,Nmon, &
                                var_ln,var_unit, lon_nm, lat_nm, z_nm, t_nm,Miss)
      Enddo
   End Subroutine Write_Verification
   !--------------------------------------------------------------------------------
   Subroutine Read_all_data (Dir_BJP,Dir_QM,Model_nm,yvarn)
      Character (Len=*) :: Dir_BJP,Dir_QM,Model_nm,yvarn        ! lead1_RegCM_VN.nc
      Character (Len=255) :: Fname
      Character (Len=6)   :: vname, vnm(Nvar-1)=(/"_o","","_bjp"/)
      Real, Allocatable :: xlon(:),xlat(:),xlev(:),xtime(:),X3d(:,:,:)
      Integer :: it,ilead,ivar,Nlo,Nla,Nz,Nt

      if (Allocated (Dat_All)) Deallocate (Dat_All)
      Do ilead=1,NLead
         !write (Fname,"(A,I1,A)") trim(Dir_BJP)//trim(yvarn)//"_lead",ilead,"_"//trim(Model_nm)//"_VN.nc" 
         write (Fname,"(A,I1,A)") trim(Dir_BJP)//"lead",ilead,"_"//trim(Model_nm)//"_VN.nc"
         Do ivar=1,Nvar-1    ! obs, mod, bjp
            vname=trim(yvarn)//trim(vnm(ivar))
            !Call rd_ncdf_4d (Fname,xlon,xlat,xlev,xtime,Nlo,Nla,Nz,Nt,X4d,trim(yvarn))
            Call rd_ncdf_3d (Fname,xlon,xlat,xtime,Nlo,Nla,Nt,X3d,trim(vname))
            if (ilead==1.AND.ivar==1) then
               Ntime=Nt 
               Allocate (Dat_All(Nlon,Nlat,Ntime,Nvar,NLead)) ! (Nlon,Nlat,Ntime,Nvar,NLead)) 
               Dat_All=Miss
            endif
            Do it=1,Ntime
               Dat_All(:,:,it,ivar,ilead)=X3d(:,:,it)
            Enddo
            Deallocate (xlon,xlat,xtime,X3d)
         Enddo
      Enddo
      Do ilead=1,NLead  ! monsum_pr_QM-lead1_RegCM_daily_baseline.nc
         if (trim(yvarn)=="pr") then 
            write (Fname,"(A,I1,A)") trim(Dir_QM)//"monsum_"//trim(yvarn)//"_QM-lead",ilead,"_"//trim(Model_nm)//"_daily_baseline.nc"
            Call rd_ncdf_3d (Fname,xlon,xlat,xtime,Nlo,Nla,Nt,X3d,trim(yvarn))
         else
            write (Fname,"(A,I1,A)") trim(Dir_QM)//"monmean_tas"//"_QM-lead",ilead,"_"//trim(Model_nm)//"_daily_baseline.nc"
            Call rd_ncdf_3d (Fname,xlon,xlat,xtime,Nlo,Nla,Nt,X3d,"tas")
         endif
         Do it=1,Nt
            Dat_All(:,:,ilead+it,Nvar,ilead)=X3d(:,:,it)
         Enddo
         Deallocate (xlon,xlat,xtime,X3d)
      Enddo
   End Subroutine Read_all_data
   !--------------------------------------------------------------------------------
   Logical Function Miss_Ar1(X,N,Miss)
      Integer :: N,i
      Real :: X(N), Miss
      Logical :: Empty

      Empty=.False.
      Do i=1,N
         if (X(i)==Miss) then
            Empty=.True.; Exit
         endif
      Enddo
      Miss_Ar1=Empty
   End Function Miss_Ar1
   !--------------------------------------------------------------------------------
     
   !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"
   !--------------------------------------------------------------------------------
   END
   Include "/home/tanpv/Mylibs/Student_Prob.f90"
   !-------------------------------------------------------------------------------------------
