!
!##################################################################
!##################################################################
!######                                                      ######
!######          SUBROUTINE MEAN_ABSOULTE_ERROR              ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################


SUBROUTINE MEAN_ABSOLUTE_ERROR (nx, ny, nz, data, model, ilevel, &
                                jlevel, klevel)

!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Calculates the mean absolute error between the hypothetical data set
!  and model forecast and writes this to the "MAE.txt" file
!
!  The file "MAE.txt" will always contain the mean absolute error for 
!  the entire data set at the top of the file.  It will also contain
!  the mean absolute error based on the i, j, or k levels depending
!  upon which of those options are chosen in the "verif.input" file.
!
!  Formula:
!
!  MAE = (1/n) * SUM[k=1 to n] ABS(y(k) - o(k))
!
!  n is the number of forecast / observation pairs
!  y(k) is the kth of n forecasts
!  o(k) is the kth of n observations               
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Geoffrey Stano
!  03/01/2002 Initialized.
!
!  MODIFICATIONS:
!
!  04/04/2002 Jason J. Levit
!  Cosmetic modifications.
!
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------

       IMPLICIT none

       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios

       REAL :: maez(nz)
       REAL :: maey(ny)
       REAL :: maex(nx)
       REAL :: mae_all   !  variable for MAE of entire data set 
       REAL :: num
       REAL :: data(nx,ny,nz), model(nx,ny,nz)

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


!  ##### Calculates mean absolute error for entire data set mae_all #####

       mae_all = 0.0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                num = 0.0
                num = model(i,j,k) - data(i,j,k)
                IF (num < 0) THEN
                   num = -1 * num  !  Performs Absolute Value
                END IF
                mae_all = mae_all + num
             END DO
          END DO
       END DO

       OPEN (UNIT = 11, FILE = "MAE.txt", IOSTAT = ios, &
       FORM = "FORMATTED")

       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF

       WRITE (11, FMT = 200)

       mae_all = mae_all / (nx * ny * nz)
       WRITE (11,'(f7.2)') mae_all

! ########## End of mae_all calculation ##########


! ##### Calculates i-level mean absolute error, meax ##### 

       IF (ilevel == 1) THEN
       DO i=1,nx
          maex(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                num = 0.0
                num = model(i,j,k) - data(i,j,k)
                IF (num < 0) THEN
                   num = -1 * num  !  Performs Absolute Value
                END IF
                maex(i) = maex(i) + num
             END DO
          END DO
       END DO
       
       WRITE (11, FMT = 201)

       DO i=1,nx   
          maex(i) = maex(i) / (ny * nz)
          WRITE (11,'(f7.2)') maex(i)
       END DO
       END IF

! ########## End of i-level mean absolute error ##########

! ##### Calculates j-level mean absolute error, maey #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          maey(j) = 0.0
          DO i=1,nx
             DO k=1,nz
                num = 0.0
                num = model(i,j,k) - data(i,j,k)
                IF (num < 0) THEN
                   num = -1 * num  !  Performs Absolute Value
                END IF
                maey(j) = maey(j) + num
             END DO
          END DO
       END DO

       WRITE (11, FMT = 202)
       
       DO j=1,ny 
          maey(j) = maey(j) / (nx * nz)
          WRITE (11,'(f7.2)') maey(j)
       END DO
       END IF

! ######### End of j-level mean absolute error ##########

! ##### Calculates the k-level mean absolute error #####

       IF (klevel == 1) THEN
       DO k=1,nz
          maez(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                num = 0.0
                num = model(i,j,k) - data(i,j,k)
                IF (num < 0) THEN
                   num = -1 * num  !  Performs Absolute Value
                END IF
                maez(k) = maez(k) + num
             END DO
          END DO
       END DO

       WRITE (11, FMT = 203)
       
       DO k=1,nz 
          maez(k) = maez(k) / (nx * ny)
          WRITE (11,'(f7.2)') maez(k)
       END DO
       END IF

! ######### End of k-level mean absolute error #########

       CLOSE (UNIT = 11)


200    FORMAT ("Mean Absolute Error for all data"/)
201    FORMAT (/"Mean Absolute Error with i-level dependence"/)
202    FORMAT (/"Mean Absolute Error with j-level dependence"/)
203    FORMAT (/"Mean Absolute Error with k-level dependence"/)

       END SUBROUTINE Mean_Absolute_Error



!#######################################################################


       SUBROUTINE BRIER_SCORE (noe, fcstprob, obsevent)


!  Calculates the brier score between the hypothetical probability
!  forecast and the observed event and writes this to the "BrierS.txt" 
!  file
!
!  Formula:
!
!  BS = (1/n) * SUM[k=1 to n] (fp(k) - v(k))**2
!
!  n is the number of forecast / observation pairs 
!  fp is the forecasted probability for an event 
!  v is the verification term 
!  v = 1 if the event did occur
!  v = 0 if the event did not occur

!#######################################################################

       IMPLICIT none
          
       INTEGER :: noe   !  number of events
       INTEGER :: g, ios
     
       REAL :: brier_s(noe)   !  brier score
       
       REAL :: fcstprob(noe), obsevent(noe)

       DO g=1,noe
          brier_s = brier_s + (fcstprob(g) - obsevent(g))**2
       END DO

       OPEN (UNIT = 22, FILE = "BrierS.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
       
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF

       WRITE (22, FMT = 300)

       brier_s(noe) = (brier_s(noe) / noe)
       WRITE (22, FMT = '(f4.2)') brier_s(noe)
   
       CLOSE(22)

300    FORMAT ("Brier Score"/)     


       END SUBROUTINE Brier_Score




!#######################################################################


       SUBROUTINE ROOT_MEAN_SQUARE (nx, ny, nz, data, model, ilevel, & 5
        jlevel, klevel,rms_all)


!  Calculates the root mean square error between the hypothetical data set
!  and the model forecast and writes this to the "RMS.txt" file
!
!  Formula:
! 
!  RMS = SQRT{ (1/n) * SUM[k=1 to n] (y(k) - o(k))**2}
!
!  n is the number of forecast / observation pairs 
!  y(k) is the kth of n forecasts
!  o(k) is the kth of n observations

!#######################################################################

       IMPLICIT none

       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios, num
       INTEGER :: rmscount

       REAL :: rms_all
       REAL :: rmsz(nz)
       REAL :: rmsy(ny)
       REAL :: rmsx(nx)
       REAL :: data(nx,ny,nz), model(nx,ny,nz)

! ##### Calulates the root mean square error for all data #####

       rms_all = 0.0
       rmscount=0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                IF (data(i,j,k).ne.-99.9) THEN
                  rms_all = rms_all + (model(i,j,k)-data(i,j,k))**2
                  rmscount=rmscount+1
                END IF
             END DO
          END DO
       END DO

!       OPEN (UNIT = 12, FILE = "RMS.txt", IOSTAT = ios, &
!       FORM = "FORMATTED")
   
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF
 
!       WRITE (12, FMT = 300)
!       print *, 'rmscount=',rmscount
!       rms_all = rms_all / (nx * ny * nz)
       rms_all = rms_all / real(rmscount)
       rms_all = SQRT(rms_all)
!       WRITE (12,'(f7.2)') rms_all

! ########## End all root mean square error ##########

! ##### Calculates the i-level root mean square error #####

       IF (ilevel == 1) THEN
       DO i=1,nx
          rmsx(i) = 0.0
          DO j=1,ny
             DO k=1,nz  
                rmsx(i) = rmsx(i) + (model(i,j,k)-data(i,j,k))**2
             END DO
          END DO
       END DO
       
!       WRITE (12, FMT = 301)

       DO i = 1,nx
          rmsx(i) = rmsx(i) / (ny * nz)
          rmsx(i) = SQRT(rmsx(i))
!          WRITE (12,'(f7.2)') rmsx(i)
       END DO
       END IF

! ########## End i-level root mean square error ##########

! ##### Calculates the j-level root mean square error #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          rmsy(j) = 0.0
          DO i=1,nx
             DO k=1,nz  
                rmsy(j) = rmsy(j) + (model(i,j,k)-data(i,j,k))**2
             END DO
          END DO
       END DO
       
!       WRITE (12, FMT = 302)

       DO j = 1,ny
          rmsy(j) = rmsy(j) / (nx * nz)
          rmsy(j) = SQRT(rmsy(j))
!          WRITE (12,'(f7.2)') rmsy(j)
       END DO
       END IF

! ########## End j-level root mean square error ##########

! ##### Calculates the k-level root mean square error #####

       IF (klevel == 1) THEN
       DO k=1,nz
          rmsz(k) = 0.0
          DO j=1,ny
             DO i=1,nx  
                rmsz(k) = rmsz(k) + (model(i,j,k)-data(i,j,k))**2
             END DO
          END DO
       END DO
       
!       WRITE (12, FMT = 303)

       DO k = 1,nz
          rmsz(k) = rmsz(k) / (nx * ny)
          rmsz(k) = SQRT(rmsz(k))
!          WRITE (12,'(f7.2)') rmsz(k)
       END DO
       END IF

! ########## End k-level root mean square error ##########
       
!       CLOSE (UNIT = 12)

300    FORMAT ("Root Mean Square Error for all data"/)
301    FORMAT (/"Root Mean Square Error with i-level dependence"/)
302    FORMAT (/"Root Mean Square Error with j-level dependence"/)
303    FORMAT (/"Root Mean Square Error with k-level dependence"/)


       END SUBROUTINE Root_Mean_Square



!#######################################################################


       SUBROUTINE MEAN_SQUARE_ERROR (nx, ny, nz, data, model, ilevel, &
         jlevel, klevel)


!  Calculates the mean square error between the hypothetical data set 
!  and the model forecast and writes this to the "MSE.txt" file
! 
!  Formula:
!
!  MSE = (1/n) * SUM[k=1 to n] (y(k) -o(k))**2
!
!  n is the number of forecast / observation pairs
!  y(k) is the kth of n forecasts
!  o(k) is the kth of n observations

!#######################################################################

       IMPLICIT none

       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios, num

       REAL :: mse_all
       REAL :: msez(nz)
       REAL :: msey(ny)
       REAL :: msex(nx)
       REAL :: data(nx,ny,nz), model(nx,ny,nz)
          
! ##### Calculates the mean square error for all data #####

       mse_all = 0.0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                mse_all = mse_all + (model(i,j,k)-data(i,j,k))**2
             END DO
          END DO
       END DO

       OPEN (UNIT = 13, FILE = "MSE.txt", IOSTAT = ios,  &
       FORM = "FORMATTED")
   
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF

       WRITE (13, FMT = 400)
       mse_all = mse_all / (nx * ny * nz)
       WRITE (13,'(f7.2)') mse_all

! ########## End mean square error for all data ##########

! ##### Calculates i-level mean square error #####

       IF (ilevel == 1) THEN
       DO i=1,nx
          msex(i) = 0.0
          DO j=1,ny   
             DO k=1,nz
                msex(i) = msex(i) + (model(i,j,k)-data(i,j,k))**2
             END DO
          END DO
       END DO
       
       WRITE (13, FMT = 401)

       DO i = 1,nx
          msex(i) = msex(i) / (ny * nz)
          WRITE (13,'(f7.2)') msex(i)
       END DO
       END IF

! ######### End i-level mean square error ##########

! ##### Calculates j-level mean square error #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          msey(j) = 0.0
          DO k=1,nz   
             DO i=1,nx
                msey(j) = msey(j) + (model(i,j,k)-data(i,j,k))**2
             END DO
          END DO
       END DO
       
       WRITE (13, FMT = 402)

       DO j = 1,ny
          msey(j) = msey(j) / (nx * nz)
          WRITE (13,'(f7.2)') msey(j)
       END DO
       END IF

! ########## End j-level mean square error ##########

! ##### Calculates k-level mean square error #####

       IF (klevel == 1) THEN
       DO k=1,nz
          msez(k) = 0.0
          DO j=1,ny   
             DO i=1,nx
                msez(k) = msez(k) + (model(i,j,k)-data(i,j,k))**2
             END DO
          END DO
       END DO
       
       WRITE (13, FMT = 403)

       DO k = 1,nz
          msez(k) = msez(k) / (nx * ny)
          WRITE (13,'(f7.2)') msez(k)
       END DO
       END IF

! ######### End k-level mean square error ##########
       
       CLOSE (UNIT = 13)

400    FORMAT ("Mean Square Error for all data"/)
401    FORMAT (/"Mean Square Error with i-level dependence"/)
402    FORMAT (/"Mean Square Error with j-level dependence"/)
403    FORMAT (/"Mean Square Error with k-level dependence"/)
       
          
       END SUBROUTINE Mean_Square_Error



!#######################################################################


       SUBROUTINE FORECAST_MEAN (nx, ny, nz, model, ilevel, jlevel, &
         klevel)


!  Calculates the mean of all of the forecast data and writes this 
!  to the "FcstMean.txt" file
!
!  Formula:
!
!  Forecast Mean = (Sum of all forecasts) / (Total number of forecasts)

!#######################################################################

       IMPLICIT none

       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios, num

       REAL :: fcstmean_all   !  mean of all forecasts
       REAL :: fcstmeanz(nz)
       REAL :: fcstmeany(ny)
       REAL :: fcstmeanx(nx)
       REAL :: model(nx,ny,nz)   !  hypothetical model data
       
! ##### Calculates the forecast mean for all data #####

      fcstmean_all = 0.0 

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                fcstmean_all = fcstmean_all + model(i,j,k)
             END DO
          END DO
       END DO

       fcstmean_all = fcstmean_all / (nx * ny * nz)

       OPEN (UNIT = 14, FILE = "FcstMean.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
       
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF
       
       WRITE (14, FMT = 500)
       WRITE (14,'(f7.2)') fcstmean_all

! ############ End forecast mean for all data ##########

! ##### Calculates i-level forecast mean #####

       IF (ilevel == 1) THEN
       DO i=1,nx      
          fcstmeanx(i) = 0.0
          DO j=1,ny   
             DO k=1,nz
                fcstmeanx(i) = fcstmeanx(i) + model(i,j,k)
             END DO
          END DO
       END DO

       WRITE (14, FMT = 501)

       DO i=1,nx       
          fcstmeanx(i) = fcstmeanx(i) / (ny * nz)
          WRITE (14,'(f7.2)') fcstmeanx(i)
       END DO
       END IF

! ########## End i-level forecast mean ##########

! ##### Calculates j-level forecast mean #####

       IF (jlevel == 1) THEN
       DO j=1,ny      
          fcstmeany(j) = 0.0
          DO k=1,nz   
             DO i=1,nx
                fcstmeany(j) = fcstmeany(j) + model(i,j,k)
             END DO
          END DO
       END DO

       WRITE (14, FMT = 502)

       DO j=1,ny       
          fcstmeany(j) = fcstmeany(j) / (nx * nz)
          WRITE (14,'(f7.2)') fcstmeany(j)
       END DO
       END IF

! ########## End j-level forecast mean ##########

! ##### Calculates k-level forecast mean #####
       
       IF (klevel == 1) THEN
       DO k=1,nz      
          fcstmeanz(k) = 0.0
          DO j=1,ny   
             DO i=1,nx
                fcstmeanz(k) = fcstmeanz(k) + model(i,j,k)
             END DO
          END DO
       END DO

       WRITE (14, FMT = 503)

       DO k=1,nz       
          fcstmeanz(k) = fcstmeanz(k) / (nx * ny)
          WRITE (14,'(f7.2)') fcstmeanz(k)
       END DO
       END IF

! ########## End k-level forecast mean ##########

       CLOSE (UNIT = 14)

500    FORMAT ("Forecast mean for all data"/)
501    FORMAT (/"Forecast mean with i-level dependence"/)
502    FORMAT (/"Forecast mean with j-level dependence"/)
503    FORMAT (/"Forecast mean with k-level dependence"/)


       END SUBROUTINE Forecast_Mean




!#######################################################################


       SUBROUTINE OBSERVATION_MEAN (nx, ny, nz, data, ilevel, jlevel, &
        klevel)


!  Calculates the mean of all of the observation data and writes this
!  to the "ObsMean.txt" file
!
!  Formula:
! 
!  Observation Mean = (Sum of all obs) / (Total number of obs)

!#######################################################################
       
       IMPLICIT none
       
       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios, num
          
       REAL :: obsmean_all   !  mean of all observations
       REAL :: obsmeanz(nz)
       REAL :: obsmeany(ny)
       REAL :: obsmeanx(nx)
       REAL :: data(nx,ny,nz)   !  hypothetical observation data
          
! ##### Calculates the mean for all the observations #####

       obsmean_all = 0.0
   
       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                obsmean_all = obsmean_all + data(i,j,k)
             END DO
          END DO   
       END DO      
       
       obsmean_all = obsmean_all / (nx * ny * nz)
       
       OPEN (UNIT = 15, FILE = "ObsMean.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
     
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF
       
       WRITE (15, FMT = 600)
       WRITE (15,'(f7.2)') obsmean_all

! ######### End observation mean for all data ##########

! ##### Calculates i-level observation mean #####

       IF (ilevel == 1) THEN
       DO i=1,nx
          obsmeanx(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                obsmeanx(i) = obsmeanx(i) + data(i,j,k)
             END DO
          END DO
       END DO

       WRITE (15, FMT = 601)

       DO i=1,nx
          obsmeanx(i) = obsmeanx(i) / (ny * nz)
          WRITE (15,'(f7.2)') obsmeanx(i)
       END DO
       END IF

! ########## End i-level observation mean #########

! ##### Calculates j-level observation mean #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          obsmeany(j) = 0.0
          DO k=1,nz
             DO i=1,nx
                obsmeany(j) = obsmeany(j) + data(i,j,k)
             END DO
          END DO
       END DO

       WRITE (15, FMT = 602)

       DO j=1,ny
          obsmeany(j) = obsmeany(j) / (nx * nz)
          WRITE (15,'(f7.2)') obsmeany(j)
       END DO
       END IF

! ########## End j-level observation mean ##########

! ##### Calculates k-level observation mean #####

       IF (klevel == 1) THEN
       DO k=1,nz
          obsmeanz(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                obsmeanz(k) = obsmeanz(k) + data(i,j,k)
             END DO
          END DO
       END DO

       WRITE (15, FMT = 603)

       DO k=1,nz
          obsmeanz(k) = obsmeanz(k) / (nx * ny)
          WRITE (15,'(f7.2)') obsmeanz(k)
       END DO
       END IF

! ########## End k-level observation mean ##########
       
       CLOSE (UNIT = 15)

600    FORMAT ("Observation mean for all data"/)
601    FORMAT (/"Observation mean with i-level dependence"/)
602    FORMAT (/"Observation mean with j-level dependence"/)
603    FORMAT (/"Observation mean with k-level dependence"/)
       
       
       END SUBROUTINE Observation_Mean
       
       


!#######################################################################


       SUBROUTINE FORECAST_VARIANCE (nx, ny, nz, model, ilevel, &
         jlevel, klevel)


!  Calculates the varience for the hypothetical forecast set and writes 
!  this to the "FcstVar.txt" file.
!
!  Formula:
!
!  Variance = SUM[ (x - x(bar))**2 / N]
!
!  x is the value of each individual forecast
!  x(bar) is the mean of the set of forecasts
!  N is the number of forecasts

!#######################################################################

       IMPLICIT none
       
       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios, num

       REAL :: avg_all   !  holds average value
       REAL :: avgz(nz)
       REAL :: avgy(ny)
       REAL :: avgx(nx)
       REAL :: fcstvar_all
       REAL :: fcstvarz(nz)
       REAL :: fcstvary(ny)
       REAL :: fcstvarx(nx)
       REAL :: model(nx,ny,nz)

! ##### Calculates forecast variance for all data #####

       avg_all = 0.0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                avg_all = avg_all + model(i,j,k)
             END DO
          END DO
       END DO

       avg_all = avg_all / (nx * ny * nz)

       fcstvar_all = 0.0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                fcstvar_all = fcstvar_all + (model(i,j,k) - avg_all)**2
             END DO
          END DO
       END DO
       
       fcstvar_all = fcstvar_all / (nx*ny*nz)

       OPEN (UNIT = 17, FILE = "FcstVar.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
       
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF
       
       WRITE (17, FMT = 700)
       WRITE (17,'(e13.2)') fcstvar_all

! ########## End forecast variance for all data ##########
          
! ##### Calculates i-level forecast variance #####

       IF (ilevel == 1) THEN
       DO i=1,nx
          avgx(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                avgx(i) = avgx(i) + model(i,j,k)
             END DO
          END DO
       END DO
       
       DO i=1,nx
          avgx(i) = avgx(i) / (ny * nz)
       END DO   
    
       DO i=1,nx
          fcstvarx(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                fcstvarx(i) = fcstvarx(i) + (model(i,j,k) - avgx(i))**2
             END DO
          END DO
       END DO

       WRITE (17, FMT = 701)

       DO i=1,nx
          fcstvarx(i) = fcstvarx(i) / (ny*nz)
          WRITE (17,'(e13.2)') fcstvarx(i)
       END DO
       END IF

! ########## End i-level forecast variance ##########

! ##### Calculates j-level forecast variance #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          avgy(j) = 0.0
          DO i=1,nx
             DO k=1,nz
                avgy(j) = avgy(j) + model(i,j,k)
             END DO
          END DO
       END DO
       
       DO j=1,ny
          avgy(j) = avgy(j) / (nx * nz)
       END DO
          
       DO j=1,ny
          fcstvary(j) = 0.0
          DO i=1,nx
             DO k=1,nz
                fcstvary(j) = fcstvary(j) + (model(i,j,k) - avgy(j))**2
             END DO
          END DO
       END DO
       
       WRITE (17, FMT = 702)
       
       DO j=1,ny
          fcstvary(j) = fcstvary(j) / (nx * nz)
          WRITE (17,'(e13.2)') fcstvary(j)
       END DO
       END IF

! ########## End j-level forecast variance ##########

! ##### Calculates k-level forecast variance #####

       IF (klevel == 1) THEN
       DO k=1,nz
          avgz(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                avgz(k) = avgz(k) + model(i,j,k)
             END DO
          END DO
       END DO
       
       DO k=1,nz
          avgz(k) = avgz(k) / (nx * ny)
       END DO
          
       DO k=1,nz
          fcstvarz(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                fcstvarz(k) = fcstvarz(k) + (model(i,j,k) - avgz(k))**2
             END DO
          END DO
       END DO
       
       WRITE (17, FMT = 703)
       
       DO k=1,nz
          fcstvarz(k) = fcstvarz(k) / (nx * ny)
          WRITE (17,'(e13.2)') fcstvarz(k)
       END DO
       END IF

! ########## End k-level forecast variance ##########

       CLOSE (17)

700    FORMAT ("Forecast Variance with all data"/)
701    FORMAT (/"Forecast Variance with i-level dependence"/)
702    FORMAT (/"Forecast Variance with j-level dependence"/)
703    FORMAT (/"Forecast Variance with k-level dependence"/)


       END SUBROUTINE FORECAST_VARIANCE



!#######################################################################
       

       SUBROUTINE OBSERVATION_VARIANCE (nx, ny, nz, obs, ilevel, &
         jlevel, klevel)
       
          
!  Calculates the varience for the hypothetical forecast set and writes
!  this to the "FcstVar.txt" file.
!
!  Formula:
!
!  Variance = SUM[ (x - x(bar))**2 / N]
!
!  x is the value of each individual observation
!  x(bar) is the mean of the set of observations
!  N is the number of observations
             
!#######################################################################

       IMPLICIT none
       
       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation   
       INTEGER :: i, j ,k, ios, num
          
       REAL :: avg_all   !  holds average value
       REAL :: avgz(nz)
       REAL :: avgy(ny)
       REAL :: avgx(nx)
       REAL :: obsvar_all
       REAL :: obsvarz(nz)
       REAL :: obsvary(ny)
       REAL :: obsvarx(nx)
       REAL :: obs(nx,ny,nz), model(nx,ny,nz)

! ##### Calculates observation variance for all data #####

       avg_all = 0.0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                avg_all = avg_all + obs(i,j,k)
             END DO
          END DO
       END DO

       avg_all = avg_all / (nx * ny * nz)

       obsvar_all = 0.0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                obsvar_all = obsvar_all + (obs(i,j,k) - avg_all)**2
             END DO
          END DO
       END DO
       
       obsvar_all = obsvar_all / (nx*ny*nz)

       OPEN (UNIT = 18, FILE = "ObsVar.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
       
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF
       
       WRITE (18, FMT = 800)
       WRITE (18,'(e13.2)') obsvar_all

! ########## End observation variance for all data ##########
          
! ##### Calculates i-level observation variance #####

       IF (ilevel == 1) THEN
       DO i=1,nx
          avgx(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                avgx(i) = avgx(i) + obs(i,j,k)
             END DO
          END DO
       END DO
       
       DO i=1,nx
          avgx(i) = avgx(i) / (ny * nz)
       END DO   
    
       DO i=1,nx
          obsvarx(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                obsvarx(i) = obsvarx(i) + (obs(i,j,k) - avgx(i))**2
             END DO
          END DO
       END DO

       WRITE (18, FMT = 801)

       DO i=1,nx
          obsvarx(i) = obsvarx(i) / (ny*nz)
          WRITE (18,'(e13.2)') obsvarx(i)
       END DO
       END IF

! ########## End i-level observation variance ##########

! ##### Calculates j-level observation variance #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          avgy(j) = 0.0
          DO i=1,nx
             DO k=1,nz
                avgy(j) = avgy(j) + obs(i,j,k)
             END DO
          END DO
       END DO

       DO j=1,ny
          avgy(j) = avgy(j) / (nx * nz)
       END DO
          
       DO j=1,ny
          obsvary(j) = 0.0
          DO i=1,nx
             DO k=1,nz
                obsvary(j) = obsvary(j) + (obs(i,j,k) - avgy(j))**2
             END DO
          END DO
       END DO
       
       WRITE (18, FMT = 802)
       
       DO j=1,ny
          obsvary(j) = obsvary(j) / (nx * nz)
          WRITE (18,'(e13.2)') obsvary(j)
       END DO
       END IF

! ########## End j-level observation variance ##########

! ##### Calculates k-level observation variance #####

       IF (klevel == 1) THEN
       DO k=1,nz
          avgz(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                avgz(k) = avgz(k) + obs(i,j,k)
             END DO
          END DO
       END DO
       
       DO k=1,nz
          avgz(k) = avgz(k) / (nx * ny)
       END DO
          
       DO k=1,nz
          obsvarz(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                obsvarz(k) = obsvarz(k) + (obs(i,j,k) - avgz(k))**2
             END DO
          END DO
       END DO
       
       WRITE (18, FMT = 803)
       
       DO k=1,nz
          obsvarz(k) = obsvarz(k) / (nx * ny)
          WRITE (18,'(e13.2)') obsvarz(k)
       END DO
       END IF

! ########## End k-level forecast variance ##########

       CLOSE (18)

800    FORMAT ("Observation Variance with all data"/)
801    FORMAT (/"Observation Variance with i-level dependence"/)
802    FORMAT (/"Observation Variance with j-level dependence"/)
803    FORMAT (/"Observation Variance with k-level dependence"/)
       CLOSE (UNIT = 18)


       END SUBROUTINE OBSERVATION_VARIANCE



!#######################################################################


       SUBROUTINE FORECAST_STD_DEVIATION (nx, ny, nz, model, ilevel, &
         jlevel, klevel)


!  Calculates the standard deviation for the hypothetical forecast data
!  set and writes this to the "FcstStdDev.txt" file
!
!  Formula:
!
!  Std Dev = SQRT[ SUM[ (x -x(bar))**2 / N]]
!
!  x is the value of each individual forecast
!  x(bar) is the mean of the set of forecasts
!  N is the number of forecasts

!#######################################################################

       IMPLICIT none
             
       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios, num

       REAL :: stddev_all   
       REAL :: stddevz(nz)
       REAL :: stddevy(ny)
       REAL :: stddevx(nx)
       REAL :: avg_all
       REAL :: avgz(nz)
       REAL :: avgy(ny)
       REAL :: avgx(nx)
       REAL :: model(nx,ny,nz)

! ##### Calculates the standard deviation for all data #####

       avg_all = 0.0
       
       DO k=1,nz
          DO j=1,ny
             DO i=1,nx   
                avg_all = avg_all + model(i,j,k)
             END DO
          END DO
       END DO
       
       avg_all = avg_all / (nx * ny * nz)

       DO k=1,nz
          avgz(k) = avgz(k) / (nx * ny)
       END DO
       
       stddev_all = 0.0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                stddev_all = stddev_all + (model(i,j,k) - avg_all)**2
             END DO
          END DO
       END DO

       OPEN (UNIT = 20, FILE = "FcstStdDev.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
          
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF   
       
       WRITE (20, FMT = 100)
       
       stddev_all = stddev_all / (nx * ny * nz)
       stddev_all = SQRT(stddev_all)
       WRITE (20,'(e13.2)') stddev_all

! ########## End standard deviation for all data ##########

! ##### Calculates i-level standard deviation #####

       IF (ilevel == 1) THEN
       DO i=1,nx
          avgx(i) = 0.0
          DO j=1,ny
             DO k=1,nz   
                avgx(i) = avgx(i) + model(i,j,k)
             END DO
          END DO
       END DO
       
       DO i=1,nx
          avgx(i) = avgx(i) / (ny * nz)
       END DO

       DO i=1,nx
          stddevx(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                stddevx(i) = stddevx(i) + (model(i,j,k) - avgx(i))**2
             END DO
          END DO
       END DO
       
       WRITE (20, FMT = 101)
       
       DO i=1,nx
          stddevx(i) = stddevx(i) / (ny * nz)
          stddevx(i) = SQRT(stddevx(i))         
          WRITE (20,'(e13.2)') stddevx(i)
       END DO
       END IF

! ########## End i-level standard deviation ##########


! ##### Calculates j-level standard deviation #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          avgy(j) = 0.0
          DO k=1,nz
             DO i=1,nx   
                avgy(j) = avgy(j) + model(i,j,k)
             END DO
          END DO
       END DO
       
       DO j=1,ny
          avgy(j) = avgy(j) / (nx * nz)
       END DO
       
       DO j=1,ny
          stddevy(j) = 0.0
          DO k=1,nz
             DO i=1,nx
                stddevy(j) = stddevy(j) + (model(i,j,k) - avgy(j))**2
             END DO
          END DO
       END DO
       
       WRITE (20, FMT = 102)
       
       DO j=1,ny
          stddevy(j) = stddevy(j) / (nx * nz)
          stddevy(j) = SQRT(stddevy(j))
          WRITE (20,'(e13.2)') stddevy(j)
       END DO
       END IF

! ########## End j-level standard deviation ##########

! ##### Calculates k-level standard deviation #####


       IF (klevel == 1) THEN
       DO k=1,nz
          avgz(k) = 0.0
          DO j=1,ny
             DO i=1,nx   
                avgz(k) = avgz(k) + model(i,j,k)
             END DO
          END DO
       END DO
       
       DO k=1,nz
          avgz(k) = avgz(k) / (nx * ny)
       END DO
       
       DO k=1,nz
          stddevz(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                stddevz(k) = stddevz(k) + (model(i,j,k) - avgz(k))**2
             END DO
          END DO
       END DO
       
       WRITE (20, FMT = 103)
       
       DO k=1,nz
          stddevz(k) = stddevz(k) / (nx * ny)
          stddevz(k) = SQRT(stddevz(k))
          WRITE (20,'(e13.2)') stddevz(k)
       END DO
       END IF

! ########## End k-level standard deviation ##########

       CLOSE(20)

100    FORMAT ("Forecast standard deviation for all data"/)
101    FORMAT (/"Forecast std dev with i-level dependence"/)
102    FORMAT (/"Forecast std dev with j-level dependence"/)
103    FORMAT (/"Forecast std dev with k-level dependence"/)


       END SUBROUTINE FORECAST_STD_DEVIATION





!#######################################################################


       SUBROUTINE OBSERVATION_STD_DEVIATION (nx, ny, nz, obs, ilevel, &
         jlevel, klevel)


!  Calculates the standard deviation for the hypothetical observation
!  set and writes this to the "ObsStdDev.txt" file
!
!  Formula:
!
!  Std Dev = SQRT[ SUM[ (x -x(bar))**2 / N]]
!
!  x is the value of each individual observation 
!  x(bar) is the mean of the set of observations 
!  N is the number of observations 

!#######################################################################

       IMPLICIT none
             
       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios, num

       REAL :: stddev_all   
       REAL :: stddevz(nz)
       REAL :: stddevy(ny)
       REAL :: stddevx(nx)
       REAL :: avg_all
       REAL :: avgz(nz)
       REAL :: avgy(ny)
       REAL :: avgx(nx)
       REAL :: obs(nx,ny,nz)

! ##### Calculates the standard deviation for all data #####

       avg_all = 0.0
       
       DO k=1,nz
          DO j=1,ny
             DO i=1,nx   
                avg_all = avg_all + obs(i,j,k)
             END DO
          END DO
       END DO
       
       avg_all = avg_all / (nx * ny * nz)

       stddev_all = 0.0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                stddev_all = stddev_all + (obs(i,j,k) - avg_all)**2
             END DO
          END DO
       END DO

       OPEN (UNIT = 21, FILE = "ObsStdDev.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
       
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF
       
       WRITE (21, FMT = 200)
       
       stddev_all = stddev_all / (nx * ny * nz)
       stddev_all = SQRT(stddev_all)
       WRITE (21,'(e13.2)') stddev_all

! ########## End standard deviation for all data ##########

! ##### Calculates i-level standard deviation #####

       IF (ilevel == 1) THEN
       DO i=1,nx
          avgx(i) = 0.0
          DO j=1,ny
             DO k=1,nz   
                avgx(i) = avgx(i) + obs(i,j,k)
             END DO
          END DO
       END DO
       
       DO i=1,nx
          avgx(i) = avgx(i) / (ny * nz)
       END DO

       DO i=1,nx
          stddevx(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                stddevx(i) = stddevx(i) + (obs(i,j,k) - avgx(i))**2
             END DO
          END DO
       END DO
       
       WRITE (21, FMT = 201)
       
       DO i=1,nx
          stddevx(i) = stddevx(i) / (ny * nz)
          stddevx(i) = SQRT(stddevx(i))         
          WRITE (21,'(e13.2)') stddevx(i)
       END DO
       END IF

! ########## End i-level standard deviation ##########


! ##### Calculates j-level standard deviation #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          avgy(j) = 0.0
          DO k=1,nz
             DO i=1,nx   
                avgy(j) = avgy(j) + obs(i,j,k)
             END DO
          END DO
       END DO
       
       DO j=1,ny
          avgy(j) = avgy(j) / (nx * nz)
       END DO
       
       DO j=1,ny
          stddevy(j) = 0.0
          DO k=1,nz
             DO i=1,nx
                stddevy(j) = stddevy(j) + (obs(i,j,k) - avgy(j))**2
             END DO
          END DO
       END DO
       
       WRITE (21, FMT = 202)
       
       DO j=1,ny
          stddevy(j) = stddevy(j) / (nx * nz)
          stddevy(j) = SQRT(stddevy(j))
          WRITE (21,'(e13.2)') stddevy(j)
       END DO
       END IF

! ########## End j-level standard deviation ##########

! ##### Calculates k-level standard deviation #####


       IF (klevel == 1) THEN
       DO k=1,nz
          avgz(k) = 0.0
          DO j=1,ny
             DO i=1,nx   
                avgz(k) = avgz(k) + obs(i,j,k)
             END DO
          END DO
       END DO
       
       DO k=1,nz
          avgz(k) = avgz(k) / (nx * ny)
       END DO
       
       DO k=1,nz
          stddevz(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                stddevz(k) = stddevz(k) + (obs(i,j,k) - avgz(k))**2
             END DO
          END DO
       END DO
       
       WRITE (21, FMT = 203)
       
       DO k=1,nz
          stddevz(k) = stddevz(k) / (nx * ny)
          stddevz(k) = SQRT(stddevz(k))
          WRITE (21,'(e13.2)') stddevz(k)
       END DO
       END IF

! ########## End k-level standard deviation ##########

       CLOSE(21)

200    FORMAT ("Observation standard deviation for all data"/)
201    FORMAT (/"Observation std dev with i-level dependence"/)
202    FORMAT (/"Observation std dev with j-level dependence"/)
203    FORMAT (/"Observation std dev with k-level dependence"/)


       END SUBROUTINE OBSERVATION_STD_DEVIATION




!#######################################################################


       SUBROUTINE BIAS_CALC (nx, ny, nz, data, model, ilevel, jlevel, & 5
         klevel,bias_all)

       
!  Calculates the bias along the k level of the grid between the
!  hypothetical data set and model forecast and writes this
!  to the "JBias.txt" file
!
!  Formula:
!  
!  Bias = (1/n) * SUM[k=1 to n] (y(k) - o(k))
!      
!  n is the number of forecast / observation pairs
!  y(k) is the kth of n forecasts
!  o(k) is the kth of n observations

!####################################################################### 


       IMPLICIT none
       
       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios, num
       INTEGER :: biascount
       
       REAL :: bias_all
       REAL :: biasz(nz)
       REAL :: biasy(ny)
       REAL :: biasx(nx)
       REAL :: data(nx,ny,nz), model(nx,ny,nz)
       
! ##### Calclulates the bias for all data #####

       bias_all = 0.0
       biascount=0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                IF (data(i,j,k).ne.-99.9) THEN
                bias_all = bias_all + (model(i,j,k)-data(i,j,k))
                biascount=biascount+1
                END IF
             END DO
          END DO
       END DO

!       OPEN (UNIT = 16, FILE = "Bias.txt", IOSTAT = ios, &
!       FORM = "FORMATTED")

!       IF (ios /= 0) THEN
!          PRINT*, "Error opening file"
!       END IF

!       WRITE (16, FMT = 900)

!       bias_all = bias_all / (nx * ny * nz)
        bias_all = bias_all / (biascount)
!       WRITE (16,'(f7.2)') bias_all

! ########## End bias for all data ##########

! ##### Calculates i-level bias ######

       IF (ilevel == 1) THEN
       DO i=1,nx
          biasx(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                biasx(i) = biasx(i) + (model(i,j,k)-data(i,j,k))
             END DO
          END DO
       END DO
       
       WRITE (16, FMT = 901)
       
       DO i = 1,nx
          biasx(i) = biasx(i) / (ny * nz)
          WRITE (16,'(f7.2)') biasx(i)
       END DO
       END IF

! ########## End i-level bias ##########

! ##### Calculates j-level bias #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          biasy(j) = 0.0
          DO k=1,nz
             DO i=1,nx
                biasy(j) = biasy(j) + (model(i,j,k)-data(i,j,k))
             END DO
          END DO
       END DO
       
       WRITE (16, FMT = 902)
       
       DO j = 1,ny
          biasy(j) = biasy(j) / (nx * nz)
          WRITE (16,'(f7.2)') biasy(j)
       END DO
       END IF

! ########## End j-level bias ##########

! ##### Calculate k-level bias #####

       IF (klevel == 1) THEN
       DO k=1,nz
          biasz(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                biasz(k) = biasz(k) + (model(i,j,k)-data(i,j,k))
             END DO
          END DO
       END DO
       
       WRITE (16, FMT = 903)

       DO k = 1,nz
          biasz(k) = biasz(k) / (nx * ny)
          WRITE (16,'(f7.2)') biasz(k)
       END DO
       END IF

! ########## End k-level bias ##########

       
       CLOSE (UNIT = 16)

900    FORMAT ("Bias for all data"/)
901    FORMAT (/"Bias with i-level dependence"/)
902    FORMAT (/"Bias with j-level dependence"/)
903    FORMAT (/"Bias with k-level dependence"/)


       END SUBROUTINE BIAS_CALC




!#######################################################################
       

       SUBROUTINE THREAT_SCORE (noe, fcstprob, obsevent)
       
       
!  Calculates the threat score using hypothetical data from a 
!  probability forecast and writes this calculation to the
!  "TS.txt" file.  This calculation also goes by the name
!  Critical Success Index (CSI).
!
!  Formula:
!
!  Threat Score =  CFE(y) / [ FE(y) + OE(y) - CFE(y) ]
!      
!  
!  CFE(y) is the number of correctly forecast 'yes' events
!  FE(y) is the number of forecast 'yes' events
!  OE(y) is the number of observed 'yes' events

!#######################################################################

       IMPLICIT none
       
       INTEGER :: noe   !  number of events
       INTEGER :: g, ios
       REAL :: cfey  !  number of correctly forecast 'yes' events
       REAL :: fey   !  number of forecast 'yes' events
       REAL :: oey   !  number of observed 'yes' events
          
       REAL :: threat   !  threat score
       
       REAL :: fcstprob(noe), obsevent(noe)

       cfey = 0
       fey  = 0
       oey  = 0

       DO g=1,noe
          IF ((fcstprob(g).gt.(.50)).AND.(obsevent(g) == 1.0)) THEN
             cfey = cfey + 1
          END IF
       END DO

       DO g=1,noe
          IF (fcstprob(g).gt.(.50)) THEN
             fey = fey + 1
          END IF
       END DO

       DO g=1,noe
          IF (obsevent(g) == 1) THEN
             oey = oey + 1
          END IF
       END DO

       threat = cfey / ( fey + oey - cfey )

       OPEN (UNIT = 23, FILE = "TS.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
       
       IF (ios /= 0) THEN   
          PRINT*, "Error opening file"
       END IF
       
       WRITE (23, FMT = 100)
       WRITE (23, '(f7.4)') threat

       CLOSE (23)

100    FORMAT ("Threat Score"/)


       END SUBROUTINE THREAT_SCORE



!#######################################################################
       

       SUBROUTINE EQUITABLE_THREAT_SCORE (noe, fcstprob, obsevent)
       
       
!  Calculates the equitable threat score using hypothetical data from a
!  probability forecast and writes this calculation to the
!  "ETS.txt" file. 
!      
!  Formula:
!
!  Equitable Threat Score =(CFE(y) - RH) / [FE(y) + OE(y) - CFE(y) - RH]
!
!  RH = (FE(y) * OE(y)) / n
!
!  RH is the number of hits above the threshold that would be expected
!     in a random forecast
!  CFE(y) is the number of correctly forecast 'yes' events
!  FE(y) is the number of forecast 'yes' events
!  OE(y) is the number of observed 'yes' events
!  n is the total number of forecasts
       
!#######################################################################
       
       IMPLICIT none
             
       INTEGER :: noe   !  number of events
       INTEGER :: g, ios
       REAL :: cfey  !  number of correctly forecast 'yes' events
       REAL :: fey   !  number of forecast 'yes' events
       REAL :: oey   !  number of observed 'yes' events
       REAL :: rh    !  random hits             

       REAL :: ets   !  equitable threat score
       
       REAL :: fcstprob(noe), obsevent(noe)
       
       cfey = 0
       fey  = 0
       oey  = 0

       DO g=1,noe
          IF ((fcstprob(g).gt.(.50)).AND.(obsevent(g) == 1.0)) THEN
             cfey = cfey + 1
          END IF
       END DO
       
       DO g=1,noe
          IF (fcstprob(g).gt.(.50)) THEN
             fey = fey + 1
          END IF
       END DO

       DO g=1,noe
          IF (obsevent(g) == 1) THEN
             oey = oey + 1
          END IF
       END DO

       rh = (fey * oey) / noe


       ets = (cfey - rh) / (fey + oey - cfey -rh)
       
       OPEN (UNIT = 24, FILE = "ETS.txt", IOSTAT = ios, &
       FORM = "FORMATTED")

       IF (ios /= 0) THEN 
          PRINT*, "Error opening file"
       END IF
 
       WRITE (24, FMT = 100)
       WRITE (24, '(f7.4)') ets

       CLOSE (24)

100    FORMAT ("Equitable Threat Score"/)


       END SUBROUTINE EQUITABLE_THREAT_SCORE




!#######################################################################


       SUBROUTINE PROB_OF_DETECTION (noe, fcstprob, obsevent)
       
       
!  Calculates the probability of detection using hypothetical data 
!  from a probability forecast and writes this calculation to the
!  "POD.txt" file.
!
!  Formula:
!
!  Probability of Detection = CFE(y) / OE(y)
!
!  CFE(y) is the number of correctly forecast 'yes' events
!  OE(y) is the number of observed 'yes' events
          
!#######################################################################
          
       IMPLICIT none

       INTEGER :: noe   !  number of events
       INTEGER :: g, ios
       REAL :: cfey  !  number of correctly forecast 'yes' events
       REAL :: oey   !  number of observed 'yes' events
       
       REAL :: pod   !  probability of detection
             
       REAL :: fcstprob(noe), obsevent(noe)
       
       cfey = 0
       oey  = 0

       DO g=1,noe
          IF ((fcstprob(g).gt.(.50)).AND.(obsevent(g) == 1.0)) THEN
             cfey = cfey + 1
          END IF
       END DO
       
       DO g=1,noe
          IF (obsevent(g) == 1) THEN
             oey = oey + 1
          END IF
       END DO

       pod = cfey / oey

       OPEN (UNIT = 25, FILE = "POD.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
       
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF
             
       WRITE (25, FMT = 100)
       WRITE (25, '(f7.4)') pod
   
       CLOSE (25)
          
100    FORMAT ("Probability of Detection"/)
          
       
       END SUBROUTINE PROB_OF_DETECTION




!#######################################################################
       

       SUBROUTINE FALSE_ALARM_RATE (noe, fcstprob, obsevent)
       
       
!  Calculates the false alarm rate using hypothetical data
!  from a probability forecast and writes this calculation to the
!  "FAR.txt" file.
!
!  Formula:
!            
!  False Alarm Rate = IFE(n) / FE(y)
!
!  IFE(n) is the number of incorrectly forecast 'no' events
!     (ie: The event was forecast but not observed.)
!  FE(y) is the number of forecast 'yes' events
       
!#######################################################################
       
       IMPLICIT none
             
       INTEGER :: noe   !  number of events
       INTEGER :: g, ios
       REAL :: ifen  !  number of incorrectly forecast 'yes' events
       REAL :: fey   !  number of forecast 'yes' events

       REAL :: far   !  false alarm rate
     
       REAL :: fcstprob(noe), obsevent(noe)
       
       ifen = 0
       fey  = 0

       DO g=1,noe
          IF ((fcstprob(g).gt.(.50)).AND.(obsevent(g) == 0.0)) THEN
             ifen = ifen + 1
          END IF 
       END DO
       
       DO g=1,noe
          IF (fcstprob(g).gt.(.50)) THEN
             fey = fey + 1
          END IF
       END DO

       far = ifen / fey

       OPEN (UNIT = 26, FILE = "FAR.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
       
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF  

       WRITE (26, FMT = 100)
       WRITE (26, '(f7.4)') far
             
       CLOSE (26)
       
100    FORMAT ("False Alarm Rate"/)
       
          
       END SUBROUTINE FALSE_ALARM_RATE





!######################################################################


       SUBROUTINE HIT_RATE (noe, fcstprob, obsevent)
       

!  Calculates the hit rate using hypothetical data from a probability
!  forecast and writes this calculation to the "HR.txt" file.
!      
!  Formula:
!
!  Hit Rate = (CFE(y) + CFE(n)) / n
!
!  CFE(y) is the number of correctly forecast 'yes' events
!  CFE(n) is the number of correctly forecast 'no' events
!  n is the total number of forecasts
       
!#######################################################################
       
       IMPLICIT none
             
       INTEGER :: noe   !  number of events
       INTEGER :: g, ios
       REAL :: cfey  !  number of correctly forecast 'yes' events
       REAL :: cfen  !  number of correctly forecast 'no' events
       
       REAL :: hr   !  hit rate
     
       REAL :: fcstprob(noe), obsevent(noe)
       
       cfey = 0.0
       cfen = 0.0
       
       DO g=1,noe
          IF ((fcstprob(g).gt.(.50)).AND.(obsevent(g) == 1.0)) THEN
             cfey = cfey + 1
          END IF 
       END DO

       DO g=1,noe
          IF ((fcstprob(g).le.(.50)).AND.(obsevent(g) == 0.0)) THEN
             cfen = cfen + 1
          END IF
       END DO

       hr = (cfey + cfen) / noe

       OPEN (UNIT = 27, FILE = "HR.txt", IOSTAT = ios, &
       FORM = "FORMATTED")
       
       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF

       WRITE (27, FMT = 100)
       WRITE (27, '(f7.4)') hr
 
       CLOSE (27)
 
100    FORMAT ("Hit Rate"/)


       END SUBROUTINE HIT_RATE



!#######################################################################


       SUBROUTINE SKILL_SCORE (nx, ny, nz, model, ilevel, &
         jlevel, klevel)


!  Calculates the skill score using the hypothetical model forecast
!  and a hypothetical reference value writes this to the "SS.txt" file
!
!  The file "SS.txt" will always contain the mean absolute error for 
!  the entire data set at the top of the file.  It will also contain
!  the mean absolute error based on the i, j, or k levels depending
!  upon which of those options are chosen in the "verif.input" file.
!
!
!  Formula:
!
!  MAE = (1/n) * SUM (forecast - reference) / (1 - reference)
!
!  n is the number of forecasts
!  forecast is the forecast value
!  reference is the "climotology" or "persistance" value               

!#######################################################################

       IMPLICIT none

       INTEGER :: nx   !  number of x grid points
       INTEGER :: ny   !  number of y grid points
       INTEGER :: nz   !  number of z grid points
       INTEGER :: ilevel   !  toggles ilevel calculation
       INTEGER :: jlevel   !  toggles jlevel calculation
       INTEGER :: klevel   !  toggles klevel calculation
       INTEGER :: i, j ,k, ios

       REAL :: ssz(nz)
       REAL :: ssy(ny)
       REAL :: ssx(nx)
       REAL :: ss_all   !  variable for SS of entire data set 
       REAL :: num
       REAL :: ref   !  reference value
       REAL :: model(nx,ny,nz)

!  ##### Calculates skill score for entire data set mae_all #####

       ss_all = 0.0
       ref = 50.0

       DO k=1,nz
          DO j=1,ny
             DO i=1,nx
                num = 0.0
                num = (model(i,j,k) - ref) / (1 - ref) 
                ss_all = ss_all + num
             END DO
          END DO
       END DO

       OPEN (UNIT = 28, FILE = "SS.txt", IOSTAT = ios,  &
       FORM = "FORMATTED")

       IF (ios /= 0) THEN
          PRINT*, "Error opening file"
       END IF

       WRITE (28, FMT = 200)

       ss_all = ss_all / (nx * ny * nz)
       WRITE (28,'(f7.2)') ss_all

! ########## End of ss_all calculation ##########


! ##### Calculates i-level skill score, ssx ##### 

       IF (ilevel == 1) THEN
       DO i=1,nx
          ssx(i) = 0.0
          DO j=1,ny
             DO k=1,nz
                num = 0.0
                num = (model(i,j,k) - ref) / (1 - ref)
                ssx(i) = ssx(i) + num
             END DO
          END DO
       END DO
       
       WRITE (28, FMT = 201)

       DO i=1,nx   
          ssx(i) = ssx(i) / (ny * nz)
          WRITE (28,'(f7.2)') ssx(i)
       END DO
       END IF

! ########## End of i-level skill score ##########

! ##### Calculates j-level skill score, ssy #####

       IF (jlevel == 1) THEN
       DO j=1,ny
          ssy(j) = 0.0
          DO i=1,nx
             DO k=1,nz
                num = 0.0
                num = (model(i,j,k) - ref) / (1 - ref)
                ssy(j) = ssy(j) + num
             END DO
          END DO
       END DO

       WRITE (28, FMT = 202)
       
       DO j=1,ny 
          ssy(j) = ssy(j) / (nx * nz)
          WRITE (28,'(f7.2)') ssy(j)
       END DO
       END IF

! ######### End of j-level skill score ##########

! ##### Calculates the k-level skill score #####

       IF (klevel == 1) THEN
       DO k=1,nz
          ssz(k) = 0.0
          DO j=1,ny
             DO i=1,nx
                num = 0.0
                num = (model(i,j,k) - ref) / (1 - ref)
                ssz(k) = ssz(k) + num
             END DO
          END DO
       END DO

       WRITE (28, FMT = 203)
       
       DO k=1,nz 
          ssz(k) = ssz(k) / (nx * ny)
          WRITE (28,'(f7.2)') ssz(k)
       END DO
       END IF

! ######### End of k-level skill score #########

       CLOSE (UNIT = 28)


200    FORMAT ("Skill Score for all data"/)
201    FORMAT (/"Skill Score with i-level dependence"/)
202    FORMAT (/"Skill Score with j-level dependence"/)
203    FORMAT (/"Skill Score with k-level dependence"/)

       END SUBROUTINE SKILL_SCORE