! scaleops.f90
! f90 main program written on 10.01.00 by Tim Mitchell
! last modification on 09.05.00
! f90 -o scaleops initialmod.f90 loadmod.f90 scalemod.f90 savemod.f90 transformmod.f90 scaleops.f90

program ScaleOps

use InitialMod
use LoadMod
use ScaleMod
use SaveMod
use TransformMod

implicit none

!*******************************************************************************

real, pointer, dimension (:)		:: WorkRegAye, WorkAllErrorStat
real, pointer, dimension (:)		:: TempUnSmoo, TempLowSmoo, TempHighSmoo
real, pointer, dimension (:)		:: WorkErrorMSE, WorkInternalMSE, WorkFractionMSE
real, pointer, dimension (:)		:: WorkDiffErrorMSE, WorkDiffInternalMSE, WorkDiffFractionMSE
real, pointer, dimension (:)		:: WorkSpaceA, WorkSpaceB, WorkSpaceR
real, pointer, dimension (:)		:: WorkInExe, WorkInWye, WorkOutReg, RegToBeSaved
real, pointer, dimension (:,:)		:: TimSeries, WorkAllFractionMSE, LinToBeSaved 
real, pointer, dimension (:,:)		:: WorkTimeABR, WorkSpaceABR 
real, pointer, dimension (:,:)		:: WorkActualExe, WorkActualWye, WorkPredictWye, WorkPredictor
real, pointer, dimension (:,:)		:: WorkOutExe, WorkOutWye, WorkOutTim
real, pointer, dimension (:,:,:)	:: WorkPredictand

integer, pointer, dimension (:)		:: WorkADYear, WorkMapRawReg, WorkRegSizes
integer, pointer, dimension (:,:)	:: WorkMapIDLRaw, WorkMapIDLReg

character (len=20), pointer, dimension (:) 	:: WorkRegNames 
character (len=80), pointer, dimension (:) 	:: TimRegNames, LinToBeSavedNames

real, allocatable, dimension (:,:,:)	:: WorkAllPredict, WorkAllActual

integer, allocatable, dimension (:) 	:: SaveRegKey, MemKey

character (len=10), allocatable, dimension (:)	:: MemberName

real, parameter :: MissVal = -999.0

real :: WorkAye, WorkBee, WorkPea, ErrStatStatThreshold
real :: LSRAye, LSRBee, LSRPea
real :: RegTotal, RegEn, YearTotal, YearEn, Threshold, ActualTotal, PredictTotal, MemEn
real :: WorkMissAccept		! the % acceptable missing values ; default = 10
real :: ParticAye
real :: OpTotal, OpEn
real :: MemThresh

integer :: WorkGrid,WorkLongN,WorkLatN,WorkDataN
integer :: WorkYearN,WorkDecN
integer :: WorkRegN
integer :: SaveLinN
integer :: XYear, XMem, XReg, XLine, XDec, XPredictand, XPredictor, XGloFile
integer :: ReadStatus, AllocStat
integer :: WorkMemN
integer :: TimRegN
integer :: PredictorReg
integer :: MainMenuChoice
integer :: GaussChoice
integer :: SaveRegSelect
integer :: TotRegSelect
integer :: PredictActive	! 1=Predictor and Predictand are activated 
integer :: AyeActive		! 1=WorkRegAye is activated
integer :: ErrStatMethod,ErrStatYear0,ErrStatYear1, ErrStatMissThreshold
integer :: WorkSliceLen
integer :: SaveErrStat, SaveCorrStat, SaveDiffStat
integer :: SaveTimeABR, SaveSpaceA, SaveSpaceB, SaveSpaceR
integer :: SelectMem, SelectMemN, XSelectMem
integer :: SelectADYear, SelectXYear, SelectDiffLin, SelectNatLin
integer :: QEnsSlice, QDiffScat, QGloRMSE, QDiffTim, QIntraVar, QSampPop
integer :: TotalMiss, TotalMissAye, TotalMissBee, TotalMissPea

character (len=10) :: WorkGridTitle
character (len=40) :: WorkRegTitle
character (len=80) :: WorkGridFilePath, WorkGloTitle, SaveLinTitle

!*******************************************************************************
! main routine

open (99,file="/cru/u2/f709762/data/scratch/log-scale.txt",status="replace",action="write")

call Preliminaries

do
  call MainMenu
  
  if (MainMenuChoice.EQ. 1) then
    call EnsembleSize
    call GetTimFiles
  end if
  
  if (MainMenuChoice.EQ. 2) call CalcAye
  if (MainMenuChoice.EQ. 3) call SaveAyeGlo
  if (MainMenuChoice.EQ. 4) call LoadAyeGlo  
  if (MainMenuChoice.EQ. 5) call ScalingPrediction
  if (MainMenuChoice.EQ. 6) call CalcNatVar
  if (MainMenuChoice.EQ. 7) call SetMissAccept (WorkMissAccept)
  
  if (MainMenuChoice.EQ.99) exit
end do

call WindDown

close (99)

contains

!*******************************************************************************
! main menu

subroutine MainMenu

print*, "  > Make your selection: "
print*, "  >   1. Load ensemble of model predictors and predictands."
print*, "  >   2. Use current ensemble to construct scaling equation by LSR."
print*, "  >   3. Save scaling equation to .glo file."
print*, "  >   4. Load scaling equation from .glo file."
print*, "  >   5. Apply current scaling equation to current ensemble."
print*, "  >   6. Examine nat var of current ensemble."
print*, "  >   7. Alter acceptable % of MissVal, currently: ", WorkMissAccept
print*, "  >  99. Exit."

do
	read (*,*,iostat=ReadStatus), MainMenuChoice
	if (ReadStatus.LE.0 .AND. MainMenuChoice.GE.1) exit
end do

end subroutine MainMenu

!*******************************************************************************
! preliminaries

subroutine Preliminaries

WorkMissAccept = 10.0		! default value for acceptable missing values

print*
print*, "  > ***** ScaleOps *****"
print*, "  > Performs scaling operations"
print*

print*, "  > Make initial selections that will govern all operations."

call GridSelect   (WorkGrid,WorkGridTitle,WorkLongN,WorkLatN,WorkDataN,WorkGridFilePath)
call PeriodSelect (WorkYearN,WorkDecN,WorkADYear)
call RegSelect    (WorkGrid,WorkLongN,WorkLatN,WorkDataN,WorkMapIDLReg,WorkRegSizes,WorkRegNames,&
		   WorkRegTitle,WorkRegN)

print*

end subroutine Preliminaries

!*******************************************************************************
! specify ensemble size

subroutine EnsembleSize

if (PredictActive.EQ.1) then
  deallocate (WorkPredictor,WorkPredictand,stat=AllocStat)
  if (AllocStat.EQ.0) PredictActive = 0
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Deallocation failure #####"
end if

print*, "  > Enter the number of runs to load: "
do
	read (*,*,iostat=ReadStatus), WorkMemN
	if (ReadStatus.LE.0 .AND. WorkMemN.GE.1) exit
end do

allocate ( WorkPredictor  (WorkMemN,WorkYearN), &
	   WorkPredictand (WorkRegN,WorkMemN,WorkYearN), stat=AllocStat)
if (AllocStat.EQ.0) PredictActive = 1
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

WorkPredictor  = MissVal
WorkPredictand = MissVal

allocate ( MemberName  (WorkMemN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

end subroutine EnsembleSize

!*******************************************************************************
! get .tim files

subroutine GetTimFiles

print*, "  > Load time series from .tim files."
print*, "  > Predictor is independent of choices made thus far, except years."
print*, "  > Predictand must be of correct region set and years."

do XMem = 1, WorkMemN
  print*, "  > *** MEMBER ", XMem
  print*, "  > Name this member: "
  
  do
	read (*,*,iostat=ReadStatus), MemberName(XMem)
	if (ReadStatus.LE.0.AND.MemberName(XMem).NE."") exit
  end do
  
  write (99,"(a8,a20)"), "member: ", MemberName(XMem)

  print*, "  > PREDICTOR:"
  call LoadTim (WorkYearN,WorkADYear,TimRegN,TimRegNames,TimSeries)
    
  if (TimRegN.GT.1) then
    	print*, "  > Select a region (0=display list): "
    	do
		read (*,*,iostat=ReadStatus), PredictorReg
		if (PredictorReg.EQ.0) then
		  do XReg = 1, TimRegN
		    print "(I6,A1,A40)", XReg, " ", trim(adjustl(TimRegNames(XReg)))
		  end do
		end if
		if (ReadStatus.LE.0.AND.PredictorReg.GE.1.AND.PredictorReg.LE.TimRegN) exit
    	end do
  else
    	PredictorReg = 1
  end if
  
  TotalMiss = 0
  do XYear = 1, WorkYearN
    WorkPredictor (XMem,XYear) = TimSeries (PredictorReg,XYear)
    
    if (WorkPredictor (XMem,XYear).EQ.MissVal) TotalMiss = TotalMiss + 1
  end do
  write (99,"(a23,i10)"), "predictand: total poss: ", WorkYearN 
  write (99,"(a23,i10)"), "predictor:  total miss: ", TotalMiss
  
  deallocate (TimRegNames,TimSeries)
  
  do
    print*, "  > PREDICTAND:"
    call LoadTim (WorkYearN,WorkADYear,TimRegN,TimRegNames,TimSeries)
    
    if (TimRegN.NE.WorkRegN) print*, "  > Unacceptable .tim file due to wrong no. of regions."
    if (TimRegN.EQ.WorkRegN) exit
  end do
  
  TotalMiss = 0
  do XReg = 1, WorkRegN
   do XYear = 1, WorkYearN
    WorkPredictand (XReg,XMem,XYear) = TimSeries (XReg,XYear)
    if (WorkPredictand (XReg,XMem,XYear).EQ.MissVal) TotalMiss = TotalMiss + 1
   end do
  end do
  write (99,"(a23,i10)"), "predictand: total poss: ", (WorkRegN*WorkYearN)  
  write (99,"(a23,i10)"), "predictand: total miss: ", TotalMiss  
  
  if (XMem.NE.WorkMemN) then
  	deallocate (TimRegNames,TimSeries)
  else
  	deallocate (TimSeries)			! we require TimRegNames for any saves to .tim
  end if
  
end do

end subroutine GetTimFiles

!*******************************************************************************
! calculate  'a' in y=ax

subroutine CalcAye

allocate (MemKey(WorkMemN),stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Deallocation failure #####"
MemKey     = 0
SelectMemN = 0

if (WorkMemN.GT.1) then
  print*, "  > Enter the members to use in the calculation (99=exit): "
  do
	read (*,*,iostat=ReadStatus), SelectMem
	if (ReadStatus.LE.0.AND.SelectMem.GE.1.AND.SelectMem.LE.WorkMemN) &
		MemKey (SelectMem) = 1
	if (ReadStatus.LE.0.AND.SelectMem.EQ.99) exit
  end do
else
  MemKey (1) = 1
end if

do XMem = 1, WorkMemN
  if (MemKey(XMem).EQ.1) SelectMemN = SelectMemN + 1
end do

print*, "  > Calculate scaling eq using 30y slices ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), QEnsSlice
	if (ReadStatus.LE.0 .AND. QEnsSlice.GE.1.AND.QEnsSlice.LE.2) exit
end do
print*, "  > Calculating..."

if (AyeActive.EQ.1) then
  deallocate (WorkRegAye, stat=AllocStat)
  if (AllocStat.EQ.0) AyeActive = 0
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Deallocation failure #####"
end if

allocate (WorkActualExe  (SelectMemN,WorkYearN), &
	  WorkActualWye  (SelectMemN,WorkYearN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

allocate (WorkRegAye (WorkRegN), stat=AllocStat)
if (AllocStat.EQ.0) AyeActive = 1
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

XSelectMem = 0
do XMem = 1, WorkMemN
 if (MemKey(XMem).EQ.1) then
  XSelectMem = XSelectMem + 1
  do XYear = 1, WorkYearN
    WorkActualExe (XSelectMem,XYear) = WorkPredictor (XMem,XYear)
  end do
 end if
end do

if (QEnsSlice.EQ.2) then
  allocate (WorkOutExe(SelectMemN,WorkYearN), &
  	    WorkOutWye(SelectMemN,WorkYearN), &
  	    WorkInExe (WorkYearN),            &
  	    WorkInWye (WorkYearN),	      stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
  
  do XMem = 1, SelectMemN
   do XYear = 1, WorkYearN
    WorkOutExe (1,XYear) = WorkActualExe (XMem,XYear)
   end do
   WorkInExe = MissVal
   
   call Sliceify (1,WorkYearN,30,WorkMissAccept,WorkOutExe,WorkInExe)
   
   do XYear = 1, WorkYearN
    WorkActualExe (XMem,XYear) = WorkInExe (XYear)
   end do
  end do
end if
    
do XReg = 1, WorkRegN
  XSelectMem = 0
  do XMem = 1, WorkMemN
   if (MemKey(XMem).EQ.1) then
    XSelectMem = XSelectMem + 1
    do XYear = 1, WorkYearN
      WorkActualWye (XSelectMem,XYear) = WorkPredictand (XReg,XMem,XYear)
    end do
   end if
  end do
  
  if (QEnsSlice.EQ.2) then
   do XMem = 1, SelectMemN
    do XYear = 1, WorkYearN
     WorkOutWye (1,XYear) = WorkActualWye (XMem,XYear)
    end do
    WorkInWye = MissVal
   
    call Sliceify (1,WorkYearN,30,WorkMissAccept,WorkOutWye,WorkInWye)
   
    do XYear = 1, WorkYearN
     WorkActualWye (XMem,XYear) = WorkInWye (XYear)
    end do
   end do
  end if
  
  call LinearLSRZero (SelectMemN,WorkYearN,WorkActualExe,WorkActualWye,WorkAye)  
!  call LinearLSR (SelectMemN,WorkYearN,WorkActualExe,WorkActualWye,WorkAye,WorkBee,WorkPea)  

  WorkRegAye (XReg) = WorkAye
end do

deallocate (WorkActualExe,WorkActualWye,MemKey)
deallocate (WorkInExe,WorkInWye,WorkOutExe,WorkOutWye)

end subroutine CalcAye

!*******************************************************************************
! save region set of aye to .glo file

subroutine SaveAyeGlo

print*, "  > Enter the .glo file title (suggestions below): "
print*, trim(adjustl(WorkGridTitle)) // " : run(s) : period : " // trim(adjustl(WorkRegTitle)) &
  		// " : sc-eq 'a' : season "
do
	read (*,*,iostat=ReadStatus), WorkGloTitle
	if (ReadStatus.LE.0.AND.WorkGloTitle.NE."") exit
end do

call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGloTitle,WorkGridFilePath, &
	      WorkRegAye,WorkMapIDLReg)

end subroutine SaveAyeGlo

!*******************************************************************************
! load region set of aye from .glo file

subroutine LoadAyeGlo

if (AyeActive.EQ.1) then
  deallocate (WorkRegAye, stat=AllocStat)
  if (AllocStat.EQ.0) AyeActive = 0
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Deallocation failure #####"
end if

allocate (WorkRegAye (WorkRegN), stat=AllocStat)
if (AllocStat.EQ.0) AyeActive = 1
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

call LoadGlo (WorkLongN,WorkLatN,WorkRegN,WorkMapIDLReg,WorkRegAye)

end subroutine LoadAyeGlo

!*******************************************************************************
! make predictions using scaling eq on ensemble

subroutine ScalingPrediction

call PrepareToPredict
call SelectSaveRegions

XSelectMem = 0
do XMem = 1, WorkMemN		! load up predictor
 if (MemKey(XMem).EQ.1) then
  XSelectMem = XSelectMem + 1
  do XYear = 1, WorkYearN
    WorkActualExe (XSelectMem,XYear) = WorkPredictor (XMem,XYear)
  end do
 end if
end do

if (QEnsSlice.EQ.2) then
  allocate (WorkOutExe(SelectMemN,WorkYearN), &
  	    WorkOutWye(SelectMemN,WorkYearN), &
  	    WorkInExe (WorkYearN),            &
  	    WorkInWye (WorkYearN),	      stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
  
  do XMem = 1, SelectMemN
   write (99,"(a8,a20)"), "member: ", MemberName(XMem)

   do XYear = 1, WorkYearN
    WorkOutExe (1,XYear) = WorkActualExe (XMem,XYear)
   end do
   WorkInExe = MissVal
   
   call Sliceify (1,WorkYearN,30,WorkMissAccept,WorkOutExe,WorkInExe)
   
   TotalMiss = 0
   do XYear = 1, WorkYearN
    WorkActualExe (XMem,XYear) = WorkInExe (XYear)
    if (WorkActualExe(XMem,XYear).EQ.MissVal) TotalMiss = TotalMiss + 1
   end do
   write (99,"(a30,i10)"), "predictor: sliced: total poss: ", (WorkYearN*SelectMemN) 
   write (99,"(a30,i10)"), "predictor: sliced: total miss: ", TotalMiss
  end do
end if
    
TotalMiss = 0

do XReg = 1, WorkRegN		! loop by region
  XSelectMem = 0		! load up predictand 
  do XMem = 1, WorkMemN
   if (MemKey(XMem).EQ.1) then
    XSelectMem = XSelectMem + 1
    do XYear = 1, WorkYearN
      WorkActualWye (XSelectMem,XYear) = WorkPredictand (XReg,XMem,XYear)
    end do
   end if
  end do
  
  if (QEnsSlice.EQ.2) then
   do XMem = 1, SelectMemN
    do XYear = 1, WorkYearN
     WorkOutWye (1,XYear) = WorkActualWye (XMem,XYear)
    end do
    WorkInWye = MissVal
   
    call Sliceify (1,WorkYearN,30,WorkMissAccept,WorkOutWye,WorkInWye)
   
    do XYear = 1, WorkYearN
     WorkActualWye (XMem,XYear) = WorkInWye (XYear)
    end do
   end do
  end if
  
  WorkPredictWye  = MissVal	! initialise output arrays

  				! make predictions
  ParticAye = WorkRegAye(XReg)
  call PredictRun (SelectMemN,WorkYearN,WorkActualExe,WorkPredictWye,ParticAye)
  
  do XMem = 1, SelectMemN	! store pred and act
    do XYear = 1, WorkYearN
     if (WorkPredictWye(XMem,XYear).NE.MissVal.AND.WorkActualWye(XMem,XYear).NE.MissVal) then
      WorkAllPredict (XReg,XMem,XYear) = WorkPredictWye (XMem,XYear) 
      WorkAllActual  (XReg,XMem,XYear) = WorkActualWye  (XMem,XYear)
     else
      TotalMiss = TotalMiss + 1
     end if
    end do
  end do
  
  if (SaveErrStat.EQ.2) then	! if appropriate evaluate error of predictions
    				! the 3 at the front means calc Brier score
    WorkErrorMSE    = MissVal
    WorkInternalMSE = MissVal
    WorkFractionMSE = MissVal
    call PredictError (WorkMissAccept,3,SelectMemN,WorkYearN,WorkSliceLen,WorkActualWye,WorkPredictWye,&
    		       WorkErrorMSE,WorkInternalMSE,WorkFractionMSE)
    do XYear = 1, WorkYearN
      WorkAllFractionMSE (XReg,XYear) = WorkFractionMSE (XYear)
    end do
  end if
    				! if this region has been selected, then save a .lin
  if (SaveRegKey(XReg).EQ.1) call ActualSaveRegion    
end do
write (99,"(a34,i10)"), "predictand: predicted: total poss: ", (WorkRegN*WorkYearN*SelectMemN) 
write (99,"(a34,i10)"), "predictand: predicted: total miss: ", TotalMiss

if (SaveDiffStat.EQ.2) then
  print*, "  > OPPORTUNITIES to save diff stats to .tim and .glo and .lin"
  call DiffStatTimProcedure
  call DiffStatGloProcedure
  call DiffStatLinProcedure
  if (SelectMemN.GE.2) then
    print*, "  > 1. Calc intra-ensemble variability ? (1=no,2=yes)"
    do
	read (*,*,iostat=ReadStatus), QIntraVar
	if (ReadStatus.LE.0 .AND. QIntraVar.GE.1.AND.QIntraVar.LE.2) exit
    end do

    if (QIntraVar.EQ.2) then		
		call DiffStatNatTimProcedure
		call DiffStatNatGloProcedure
		call DiffStatNatLinProcedure
    end if
  end if
end if
if (SaveCorrStat.EQ.2) call CorrStatProcedure
if (SaveErrStat.EQ.2)  call ErrStatProcedure

deallocate (WorkActualExe,WorkActualWye,WorkPredictWye,SaveRegKey)
deallocate (WorkAllActual,WorkAllPredict)
deallocate (MemKey)
if (SaveErrStat.EQ.2)  deallocate (WorkErrorMSE,WorkInternalMSE,WorkFractionMSE, &
					WorkAllFractionMSE,WorkAllErrorStat)
if (SaveCorrStat.EQ.2) deallocate (WorkSpaceA,WorkSpaceB,WorkSpaceR,WorkTimeABR)

end subroutine ScalingPrediction

!*******************************************************************************
! prepare to predict using scaling equations

subroutine PrepareToPredict

allocate (MemKey(WorkMemN),stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Deallocation failure #####"
MemKey     = 0
SelectMemN = 0

if (WorkMemN.GT.1) then
  print*, "  > Enter the members to estimate by scaling (99=exit): "
  do
	read (*,*,iostat=ReadStatus), SelectMem
	if (ReadStatus.LE.0.AND.SelectMem.GE.1.AND.SelectMem.LE.WorkMemN) &
		MemKey (SelectMem) = 1
	if (ReadStatus.LE.0.AND.SelectMem.EQ.99) exit
  end do
else
  MemKey (1) = 1
end if

do XMem = 1, WorkMemN
  if (MemKey(XMem).EQ.1) SelectMemN = SelectMemN + 1
end do

print*, "  > Predict using 30y slices ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), QEnsSlice
	if (ReadStatus.LE.0 .AND. QEnsSlice.GE.1.AND.QEnsSlice.LE.2) exit
end do

print*, "  > Select the stats to calc."

print*, "  > 1. Calc diffs between scaled and modelled? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SaveDiffStat
	if (ReadStatus.LE.0.AND.SaveDiffStat.GE.1.AND.SaveDiffStat.LE.2) exit
end do

if (SaveDiffStat.EQ.2) then
  print*, "  > 1. Calc absolute diffs (=1) or RMSE (=2) ?"
  do
	read (*,*,iostat=ReadStatus), QGloRMSE
	if (ReadStatus.LE.0.AND.QGloRMSE.GE.1.AND.QGloRMSE.LE.2) exit
  end do
  
  if (SelectMemN.GE.2.AND.QGloRMSE.EQ.1) then
    print*, "  > 1. Calc using scatter of members (=1), or ens means (=2) ?"
    do
	read (*,*,iostat=ReadStatus), QDiffScat
	if (ReadStatus.LE.0.AND.QDiffScat.GE.1.AND.QDiffScat.LE.2) exit
    end do
  else
    QDiffScat = 1
  end if
end if

print*, "  > 2. Calc correlations between scaled and modelled? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SaveCorrStat
	if (ReadStatus.LE.0.AND.SaveCorrStat.GE.1.AND.SaveCorrStat.LE.2) exit
end do

if (SelectMemN.GT.1) then
  print*, "  > 3. Calculate the mean Brier-based score? (1=no,2=yes)"
  do
	read (*,*,iostat=ReadStatus), SaveErrStat
	if (ReadStatus.LE.0.AND.SaveErrStat.GE.1.AND.SaveErrStat.LE.2) exit
  end do
else
  SaveErrStat = 1
end if

if (SaveErrStat.EQ.2) then
  print*, "  > 3. Select the slice length over which to calc means (for MSE): "
  do
	read (*,*,iostat=ReadStatus), WorkSliceLen
	if (ReadStatus.LE.0.AND.WorkSliceLen.GT.0) exit
  end do

  print*, "  > 3. Select period over which to average Brier-based score: "
  call SetUpErrorStat (WorkMissAccept,WorkADYear,WorkYearN,WorkSliceLen,&
  		       ErrStatMethod,ErrStatYear0,ErrStatYear1,&
  		       ErrStatStatThreshold,ErrStatMissThreshold)
end if

allocate (SaveRegKey (WorkRegN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
SaveRegKey = 0

allocate (WorkAllPredict  (WorkRegN,SelectMemN,WorkYearN), &
	  WorkAllActual   (WorkRegN,SelectMemN,WorkYearN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
WorkAllActual  = MissVal
WorkAllPredict = MissVal

allocate (WorkActualExe  (SelectMemN,WorkYearN), &
	  WorkActualWye  (SelectMemN,WorkYearN), &
	  WorkPredictWye (SelectMemN,WorkYearN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
WorkActualExe  = MissVal
WorkActualWye  = MissVal
WorkPredictWye = MissVal

if (SaveErrStat.EQ.2) then
  allocate (WorkErrorMSE    (WorkYearN), &
	    WorkInternalMSE (WorkYearN), &
	    WorkFractionMSE (WorkYearN), &
	    WorkAllFractionMSE (WorkRegN,WorkYearN), &
	    WorkAllErrorStat   (WorkRegN),	     stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
  
  WorkErrorMSE       = MissVal
  WorkInternalMSE    = MissVal
  WorkFractionMSE    = MissVal
  WorkAllFractionMSE = MissVal
  WorkAllErrorStat   = MissVal
end if

if (SaveCorrStat.EQ.2) then
  allocate (WorkSpaceA (WorkRegN),    &
  	    WorkSpaceB (WorkRegN),    &
  	    WorkSpaceR (WorkRegN),    &
  	    WorkTimeABR (3,WorkYearN),stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

  WorkSpaceA  = MissVal
  WorkSpaceB  = MissVal
  WorkSpaceR  = MissVal
  WorkTimeABR = MissVal
end if

end subroutine PrepareToPredict

!*******************************************************************************
! select regions to have a .lin file saved

subroutine SelectSaveRegions

print*, "  > 4. The results for any region may be saved to .lin file."
print*, "  > 4. Enter each region to be saved (0=list, -55=select all, -99=end):"
do
	read (*,*,iostat=ReadStatus), SaveRegSelect
	
	if (ReadStatus.LE.0) then
	  if (SaveRegSelect.EQ.0) then
	    do XReg = 1, WorkRegN
	      print "(I6,A40)", XReg, WorkRegNames(XReg)
	    end do
	  end if
	  
	  if (SaveRegSelect.GE.1.AND.SaveRegSelect.LE.WorkRegN) then
	    	SaveRegKey (SaveRegSelect) = 1
	  end if
	  
	  if (SaveRegSelect.EQ.-55) then
	    do XReg = 1, WorkRegN
	    	SaveRegKey (XReg) = 1
	    end do
	  end if
	end if
		
	if (ReadStatus.LE.0.AND.SaveRegSelect.LT.0) exit
end do

TotRegSelect = 0
do XReg = 1, WorkRegN
   if (SaveRegKey(XReg).EQ.1) TotRegSelect = TotRegSelect + 1
end do
print*, "  > Total regions to be individually saved: ", TotRegSelect

end subroutine SelectSaveRegions

!*******************************************************************************
! calc of diff stat

subroutine DiffStatTimProcedure

allocate (WorkOutTim (WorkRegN,WorkYearN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: DiffStatTimProcedure: Allocation failure #####"
WorkOutTim = MissVal
    
print*, "  > 1. Save difference stats to .tim ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), QDiffTim
	if (ReadStatus.LE.0.AND.QDiffTim.GE.1.AND.QDiffTim.LE.2) exit
end do

if (QDiffTim.EQ.2) then
 MemThresh = SelectMemN * (100.0 - WorkMissAccept) / 100.0
 
 if      (QGloRMSE.EQ.1) then				! calc mean diff for each reg-year

  do XReg = 1, WorkRegN
    do XYear = 1, WorkYearN
      OpTotal = 0.0
      OpEn    = 0.0
      
      do XMem = 1, SelectMemN
        if (WorkAllPredict(XReg,XMem,XYear).NE.MissVal) then
          if (WorkAllActual(XReg,XMem,XYear).NE.MissVal) then
            OpTotal = OpTotal + WorkAllPredict(XReg,XMem,XYear) - WorkAllActual(XReg,XMem,XYear)
            OpEn    = OpEn    + 1.0
          end if
        end if
      end do
      
      if (OpEn.GT.MemThresh) then
      	WorkOutTim (XReg,XYear) = OpTotal / OpEn
      end if
    end do
  end do

 else if (QGloRMSE.EQ.2) then				! calc RMSE for each reg-year
 
  if (SelectMemN.GT.1) then
   print*, "  > Calculate for sample (=1) or population (=2) ?"
   do
	read (*,*,iostat=ReadStatus), QSampPop
	if (ReadStatus.LE.0.AND.QSampPop.GE.1.AND.QSampPop.LE.2) exit
   end do
  else
   QSampPop = 1
   print*, "  > We calc for sample, because n=1"
  end if
 
  do XReg = 1, WorkRegN
    do XYear = 1, WorkYearN
      OpTotal = 0.0
      OpEn    = 0.0
      
      do XMem = 1, SelectMemN
        if (WorkAllPredict(XReg,XMem,XYear).NE.MissVal) then
          if (WorkAllActual(XReg,XMem,XYear).NE.MissVal) then
            OpTotal = OpTotal + ((WorkAllPredict(XReg,XMem,XYear) - WorkAllActual(XReg,XMem,XYear)) ** 2)
            OpEn    = OpEn    + 1.0
          end if
        end if
      end do
      
      if (OpEn.GT.MemThresh) then
      	if (QSampPop.EQ.2) then
      	  if (OpEn.GT.1) then
            WorkOutTim (XReg,XYear) = OpTotal / (OpEn - 1)
            WorkOutTim (XReg,XYear) = sqrt ( WorkOutTim (XReg,XYear) )        	
      	  else
      	    WorkOutTim (XReg,XYear) = MissVal
      	  end if
      	else
            WorkOutTim (XReg,XYear) = OpTotal / OpEn
            WorkOutTim (XReg,XYear) = sqrt ( WorkOutTim (XReg,XYear) )        	
      	end if	
      end if
    end do
  end do

 end if
 
 print*, "  > Enter the .tim file title: "
 do
	read (*,*,iostat=ReadStatus), WorkGloTitle
	if (ReadStatus.LE.0.AND.WorkGloTitle.NE."") exit
 end do
    
 call SaveTim (WorkRegN, WorkYearN, WorkGloTitle, TimRegNames, WorkADYear, WorkOutTim)
 
end if

deallocate (WorkOutTim)

end subroutine DiffStatTimProcedure

!*******************************************************************************
! calc of diff stat

subroutine DiffStatGloProcedure

allocate (WorkOutReg (WorkRegN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
    
do
  if (QGloRMSE.EQ.1) print*, "  > 1. Enter the year AD for which to calculate reg diffs (99=end): "
  if (QGloRMSE.EQ.2) print*, "  > 1. Enter the year AD for which to calculate reg RMSE (99=end): "
  do
	read (*,*,iostat=ReadStatus), SelectADYear
	if (ReadStatus.LE.0) exit
  end do
  
  SelectXYear = 0
  XYear       = 0
  do
    XYear = XYear + 1
    if (WorkADYear(XYear).EQ.SelectADYear) SelectXYear = XYear
    if (SelectXYear.GT.0.OR.XYear.EQ.WorkYearN) exit
  end do
  
  if (SelectXYear.GT.0) then
    WorkOutReg = MissVal
    
    do XReg = 1, WorkRegN
      RegTotal   = 0.0
      RegEn      = 0.0
      
      do XMem = 1, SelectMemN
        if (WorkAllPredict(XReg,XMem,SelectXYear).NE.MissVal &
        		.AND.WorkAllActual(XReg,XMem,SelectXYear).NE.MissVal) then
          if (QGloRMSE.EQ.1) then
            RegTotal = RegTotal + WorkAllPredict(XReg,XMem,SelectXYear) - WorkAllActual(XReg,XMem,SelectXYear)
            RegEn    = RegEn    + 1
          else if (QGloRMSE.EQ.2) then
            RegTotal =RegTotal+(WorkAllPredict(XReg,XMem,SelectXYear)-WorkAllActual(XReg,XMem,SelectXYear))**2
            RegEn    = RegEn    + 1
          end if
        end if
      end do
      
      if (RegEn.GE.1) then
      	if (QGloRMSE.EQ.1) then
      		WorkOutReg(XReg) = RegTotal / RegEn		! calcs abs diff
      	else if (QGloRMSE.EQ.2) then
      		WorkOutReg(XReg) = RegTotal / RegEn
      		WorkOutReg(XReg) = sqrt (WorkOutReg(XReg))	! calcs RMSE
      	end if
      end if
    end do
    
    print*, "  > Enter the .glo file title: "
    do
	read (*,*,iostat=ReadStatus), WorkGloTitle
	if (ReadStatus.LE.0.AND.WorkGloTitle.NE."") exit
    end do
    
    call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGloTitle,WorkGridFilePath, &
	          WorkOutReg,WorkMapIDLReg)
  
  else
    if (SelectADYear.NE.99) print*, "  > Unacceptable year AD."
  end if
  
  if (SelectADYear.EQ.99) exit
end do

deallocate (WorkOutReg)

end subroutine DiffStatGloProcedure

!*******************************************************************************
! calc of diff stat (global collection)

subroutine DiffStatLinProcedure

print*, "  > 1. Save glo RMSE to .lin ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SelectDiffLin
	if (ReadStatus.LE.0.AND.SelectDiffLin.GE.1.AND.SelectDiffLin.LE.2) exit
end do

if (SelectDiffLin.EQ.2) then
  print*, "  > Calculating RMSE..."
  
  allocate (LinToBeSaved      (1,WorkYearN), &
    	    LinToBeSavedNames (1)          ,	stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"    
  LinToBeSaved          = MissVal
  LinToBeSavedNames (1) = "scaled v modelled : diff MSE across globe"
  
  if (QDiffScat.EQ.1) then
  	Threshold = real(WorkRegN) * real(SelectMemN) * (100.0 - WorkMissAccept) / 100.0
  else if (QDiffScat.EQ.2) then
  	Threshold = real(WorkRegN) * (100.0 - WorkMissAccept) / 100.0
  end if
  
  do XYear = 1, WorkYearN
    YearTotal = 0.0
    YearEn    = 0.0
    
    if (QDiffScat.EQ.1) then
      do XReg = 1, WorkRegN
       do XMem = 1, SelectMemN
        if (WorkAllPredict(XReg,XMem,XYear).NE.MissVal.AND.WorkAllActual(XReg,XMem,XYear).NE.MissVal) then
          YearTotal = YearTotal + (WorkAllPredict(XReg,XMem,XYear)-WorkAllActual(XReg,XMem,XYear)) ** 2
          YearEn    = YearEn    + 1.0
        end if
       end do
      end do
    else if (QDiffScat.EQ.2) then
      do XReg = 1, WorkRegN
       PredictTotal = 0.0
       ActualTotal  = 0.0
       MemEn        = 0.0
       
       do XMem = 1, SelectMemN
        if (WorkAllPredict(XReg,XMem,XYear).NE.MissVal.AND.WorkAllActual(XReg,XMem,XYear).NE.MissVal) then
         PredictTotal = PredictTotal + WorkAllPredict (XReg,XMem,XYear)
         ActualTotal  = ActualTotal  + WorkAllActual  (XReg,XMem,XYear)
         MemEn        = MemEn        + 1.0
        end if
       end do
       
       if (MemEn.GE.1) then
         YearTotal = YearTotal + ((PredictTotal/MemEn)-(ActualTotal/MemEn)) ** 2
         YearEn    = YearEn    + 1.0
       end if
      end do
    end if
    
    if (YearEn.GE.Threshold) then
    	LinToBeSaved(1,XYear) = YearTotal / YearEn
    	LinToBeSaved(1,XYear) = sqrt ( LinToBeSaved(1,XYear) )
    end if
  end do
  
  print*, "  > Enter the .lin file title: "
  do
	read (*,*,iostat=ReadStatus), SaveLinTitle
	if (ReadStatus.LE.0.AND.SaveLinTitle.NE."") exit
  end do

  call SaveLin (1,WorkYearN,SaveLinTitle,LinToBeSavedNames,WorkADYear,LinToBeSaved)
  
  deallocate (LinToBeSaved,LinToBeSavedNames)
end if

end subroutine DiffStatLinProcedure

!*******************************************************************************
! calc of .lin diff stat in ensemble

subroutine DiffStatNatLinProcedure

print*, "  > 1. Save RMSE of global nat var to .lin ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SelectNatLin
	if (ReadStatus.LE.0.AND.SelectNatLin.GE.1.AND.SelectNatLin.LE.2) exit
end do

if (SelectNatLin.EQ.2) then
  print*, "  > Calculating RMSE..."
  
  allocate (LinToBeSaved      (1,WorkYearN), &
    	    LinToBeSavedNames (1)          ,	stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"    
  LinToBeSaved          = MissVal
  LinToBeSavedNames (1) = "modelled v modelled : nat MSE across globe"
  
  do XYear = 1, WorkYearN
    YearTotal = 0.0
    YearEn    = 0.0
    
    do XReg = 1, WorkRegN
      do XPredictor = 1, SelectMemN
        if (WorkAllActual(XReg,XPredictor,XYear).NE.MissVal) then
          do XPredictand = 1, SelectMemN
            if (XPredictor.NE.XPredictand.AND.WorkAllActual(XReg,XPredictand,XYear).NE.MissVal) then
              YearTotal = YearTotal + (WorkAllActual(XReg,XPredictor,XYear)- &
              				WorkAllActual(XReg,XPredictand,XYear)) ** 2
              YearEn    = YearEn    + 1.0
            end if
          end do
        end if
      end do
    end do

    if (YearEn.GE.2) then
    	LinToBeSaved(1,XYear) = YearTotal / YearEn
    	LinToBeSaved(1,XYear) = sqrt (LinToBeSaved(1,XYear))
    end if
  end do
  
  print*, "  > Enter the .lin file title: "
  do
	read (*,*,iostat=ReadStatus), SaveLinTitle
	if (ReadStatus.LE.0.AND.SaveLinTitle.NE."") exit
  end do

  call SaveLin (1,WorkYearN,SaveLinTitle,LinToBeSavedNames,WorkADYear,LinToBeSaved)
  
  deallocate (LinToBeSaved,LinToBeSavedNames)
end if

end subroutine DiffStatNatLinProcedure

!*******************************************************************************
! calc of .glo diff stat in ensemble

subroutine DiffStatNatGloProcedure

print*, "  > 1. Save RMSE of regional nat var to .glo ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SelectNatLin
	if (ReadStatus.LE.0.AND.SelectNatLin.GE.1.AND.SelectNatLin.LE.2) exit
end do

if (SelectNatLin.EQ.2) then
  print*, "  > Calculating RMSE..."
  
  allocate (RegToBeSaved (WorkRegN), stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"    
  RegToBeSaved = MissVal
  
  do XReg = 1, WorkRegN
    RegTotal = 0.0
    RegEn    = 0.0
    
    do XYear = 1, WorkYearN
      do XPredictor = 1, SelectMemN
        if (WorkAllActual(XReg,XPredictor,XYear).NE.MissVal) then
          do XPredictand = 1, SelectMemN
            if (XPredictor.NE.XPredictand.AND.WorkAllActual(XReg,XPredictand,XYear).NE.MissVal) then
              RegTotal = RegTotal + (WorkAllActual(XReg,XPredictor,XYear)- &
              				WorkAllActual(XReg,XPredictand,XYear)) ** 2
              RegEn    = RegEn    + 1.0
            end if
          end do
        end if
      end do
    end do

    if (RegEn.GE.2) then
    	RegToBeSaved(XReg) = RegTotal / RegEn
    	RegToBeSaved(XReg) = sqrt (RegToBeSaved(XReg))
    end if      
  end do
  
  print*, "  > Enter the .glo file title: "
  do
	read (*,*,iostat=ReadStatus), WorkGloTitle
	if (ReadStatus.LE.0.AND.WorkGloTitle.NE."") exit
  end do

  call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGloTitle,WorkGridFilePath, &
	        RegToBeSaved,WorkMapIDLReg)
  
  deallocate (RegToBeSaved)
end if

end subroutine DiffStatNatGloProcedure

!*******************************************************************************
! calc of .tim diff stat in ensemble

subroutine DiffStatNatTimProcedure

print*, "  > 1. Save RMSE of nat var to .tim ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SelectNatLin
	if (ReadStatus.LE.0.AND.SelectNatLin.GE.1.AND.SelectNatLin.LE.2) exit
end do

if (SelectNatLin.EQ.2) then
  print*, "  > Calculate for sample (=1) or population (=2) ?"
  do
	read (*,*,iostat=ReadStatus), QSampPop
	if (ReadStatus.LE.0.AND.QSampPop.GE.1.AND.QSampPop.LE.2) exit
  end do
 
  print*, "  > Calculating RMSE..."
  
  allocate (WorkOutTim (WorkRegN,WorkYearN), stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: DiffstatNatTimProcedure: Allocation failure #####"    
  WorkOutTim = MissVal
  
  do XReg = 1, WorkRegN
   do XYear = 1, WorkYearN
    OpTotal = 0.0
    OpEn    = 0.0
    
    do XPredictor = 1, SelectMemN
       if (WorkAllActual(XReg,XPredictor,XYear).NE.MissVal) then
          OpEn = OpEn + 1.0
          
          do XPredictand = 1, SelectMemN
            if (XPredictor.NE.XPredictand.AND.WorkAllActual(XReg,XPredictand,XYear).NE.MissVal) then
              OpTotal = OpTotal + (WorkAllActual(XReg,XPredictor,XYear)- &
              				WorkAllActual(XReg,XPredictand,XYear)) ** 2
            end if
          end do
       end if
    end do

    if (OpEn.GE.2) then
      	if (QSampPop.EQ.2) then
          WorkOutTim(XReg,XYear) = OpTotal / ((OpEn - 1) ** 2)
    	  WorkOutTim(XReg,XYear) = sqrt (WorkOutTim(XReg,XYear) )
      	else
          WorkOutTim(XReg,XYear) = OpTotal / (OpEn * (OpEn - 1))
    	  WorkOutTim(XReg,XYear) = sqrt (WorkOutTim(XReg,XYear) )
      	end if	
    end if
   end do
  end do
  
  print*, "  > Enter the .tim file title: "
  do
	read (*,*,iostat=ReadStatus), WorkGloTitle
	if (ReadStatus.LE.0.AND.WorkGloTitle.NE."") exit
  end do

  call SaveTim (WorkRegN, WorkYearN, WorkGloTitle, TimRegNames, WorkADYear, WorkOutTim)
   
  deallocate (WorkOutTim, stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: DiffStatNatTimProcedure: Deallocation failure #####"    
end if

end subroutine DiffStatNatTimProcedure

!*******************************************************************************
! calc of correlation stats

subroutine CorrStatProcedure

allocate (WorkOutExe (SelectMemN,WorkYearN), &
	  WorkOutWye (SelectMemN,WorkYearN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

TotalMiss = 0
TotalMissAye = 0
TotalMissBee = 0
TotalMissPea = 0

do XReg = 1, WorkRegN		! calc spatially-varying corr
  do XMem = 1, SelectMemN
    do XYear = 1, WorkYearN
      WorkOutExe (XMem,XYear) = WorkAllActual  (XReg,XMem,XYear)
      WorkOutWye (XMem,XYear) = WorkAllPredict (XReg,XMem,XYear)
      
      if (WorkOutExe(XMem,XYear).EQ.MissVal.OR.WorkOutWye(XMem,XYear).EQ.MissVal) &
      		TotalMiss = TotalMiss + 1
    end do
  end do
  
  call LinearLSR (SelectMemN,WorkYearN,WorkOutExe,WorkOutWye,LSRAye,LSRBee,LSRPea)
  
  WorkSpaceA (XReg) = LSRAye
  WorkSpaceB (XReg) = LSRBee
  WorkSpaceR (XReg) = LSRPea
  
  if (LSRAye.EQ.MissVal) TotalMissAye = TotalMissAye + 1
  if (LSRBee.EQ.MissVal) TotalMissBee = TotalMissBee + 1
  if (LSRPea.EQ.MissVal) TotalMissPea = TotalMissPea + 1
end do

write (99,"(a33,i10)"), "corr stat data (glo): total poss: ", (WorkRegN*WorkYearN*SelectMemN) 
write (99,"(a33,i10)"), "corr stat data (glo): total miss: ", TotalMiss
write (99,"(a33,i10)"), "corr a,b,r     (glo): total poss: ", WorkRegN 
write (99,"(a33,3i10)"), "corr a,b,r     (glo): total miss: ", TotalMissAye, TotalMissBee, TotalMissPea 

deallocate (WorkOutExe,WorkOutWye)

allocate (WorkOutExe (SelectMemN,WorkRegN), &
	  WorkOutWye (SelectMemN,WorkRegN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

do XYear = 1, WorkYearN		! calc temporally-varying corr
  do XMem = 1, SelectMemN
    do XReg = 1, WorkRegN
      WorkOutExe (XMem,XReg) = WorkAllActual  (XReg,XMem,XYear)
      WorkOutWye (XMem,XReg) = WorkAllPredict (XReg,XMem,XYear)
    end do
  end do
  
  call LinearLSR (SelectMemN,WorkRegN,WorkOutExe,WorkOutWye,LSRAye,LSRBee,LSRPea)
  
  WorkTimeABR (1,XYear) = LSRAye
  WorkTimeABR (2,XYear) = LSRBee
  WorkTimeABR (3,XYear) = LSRPea
end do

deallocate (WorkOutExe,WorkOutWye)

print*, "  > 2. Save glo stats to .lin ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SaveTimeABR
	if (ReadStatus.LE.0.AND.SaveTimeABR.GE.1.AND.SaveTimeABR.LE.2) exit
end do

if (SaveTimeABR.EQ.2) then
  print*, "  > Enter the .lin file title: "
  do
	read (*,*,iostat=ReadStatus), SaveLinTitle
	if (ReadStatus.LE.0.AND.SaveLinTitle.NE."") exit
  end do
  
  allocate (LinToBeSavedNames (3), stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
  LinToBeSavedNames(1) = "global LSR 'a' y=ax+b"
  LinToBeSavedNames(2) = "global LSR 'b' y=ax+b"
  LinToBeSavedNames(3) = "global Pearson coeff"
  
  call SaveLin (3,WorkYearN,SaveLinTitle,LinToBeSavedNames,WorkADYear,WorkTimeABR)
  
  deallocate (LinToBeSavedNames)
end if

print*, "  > 2. Auto-save reg LSR stats (y=ax+b) to 3 * .glo ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SaveSpaceA
	if (ReadStatus.LE.0.AND.SaveSpaceA.GE.1.AND.SaveSpaceA.LE.2) exit
end do

if (SaveSpaceA.EQ.2) then
  print*, "  > Enter the generic .glo file title: "
  do
	read (*,*,iostat=ReadStatus), WorkGloTitle
	if (ReadStatus.LE.0.AND.WorkGloTitle.NE."") exit
  end do
  
  print*, "  > File to be saved includes: y=ax+b : a"
  call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGloTitle,WorkGridFilePath, &
	        WorkSpaceA,WorkMapIDLReg)
	        
  print*, "  > File to be saved includes: y=ax+b : b"
  call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGloTitle,WorkGridFilePath, &
	        WorkSpaceB,WorkMapIDLReg)
	        
  print*, "  > File to be saved includes: y=ax+b : r"
  call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGloTitle,WorkGridFilePath, &
	        WorkSpaceR,WorkMapIDLReg)	        
end if

end subroutine CorrStatProcedure

!*******************************************************************************
! calc of error stat

subroutine ErrStatProcedure

if (SaveErrStat.EQ.2) then
  call PredictErrorStat (WorkAllFractionMSE,WorkADYear,WorkRegN,WorkYearN,&
		         ErrStatMethod,ErrStatYear0,ErrStatYear1,&
		         ErrStatStatThreshold,ErrStatMissThreshold,WorkAllErrorStat)

  do XReg = 1, WorkRegN		! print out stat for chosen regions
    if (SaveRegKey(XReg).EQ.1) then    
      print*, "  > 3+4. Region no., mean Brier score: ", XReg, WorkAllErrorStat(XReg)
    end if
  end do

  print*, "  > 3. Enter the .glo file title: "
  do
	read (*,*,iostat=ReadStatus), WorkGloTitle
	if (ReadStatus.LE.0.AND.WorkGloTitle.NE."") exit
  end do
  
  TotalMiss = 0
  do XReg = 1, WorkRegN
      if (WorkAllErrorStat(XReg).EQ.MissVal) TotalMiss = TotalMiss + 1 
  end do
  write (9,"(a21,i10)"), "err stat: total miss: ", TotalMiss
  
  call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGloTitle,WorkGridFilePath, &
	        WorkAllErrorStat,WorkMapIDLReg)
end if

end subroutine ErrStatProcedure

!*******************************************************************************
! actual save region

subroutine ActualSaveRegion

print*, "  > 4. Save region: ", XReg, WorkRegNames (XReg)

if (SaveErrStat.EQ.2) then
  SaveLinN  = SelectMemN * 3 + 3
else
  SaveLinN  = SelectMemN * 3
end if

allocate (LinToBeSaved      (SaveLinN,WorkYearN), &
    	  LinToBeSavedNames (SaveLinN)          ,	stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
    
LinToBeSaved      = MissVal
LinToBeSavedNames = "blank"
    
if (SaveErrStat.EQ.2) then
      LinToBeSavedNames ((SelectMemN*3)+1) = "all runs: scaling MSE"
      LinToBeSavedNames ((SelectMemN*3)+2) = "all runs: control MSE"
      LinToBeSavedNames ((SelectMemN*3)+3) = "all runs: Brier score"

      do XYear = 1, WorkYearN
        LinToBeSaved (((SelectMemN*3)+1),XYear) = WorkErrorMSE    (XYear)
        LinToBeSaved (((SelectMemN*3)+2),XYear) = WorkInternalMSE (XYear)
        LinToBeSaved (((SelectMemN*3)+3),XYear) = WorkFractionMSE (XYear)
      end do
end if
    
XSelectMem = 0
do XMem = 1, WorkMemN
   if (MemKey(XMem).EQ.1) then
      XSelectMem = XSelectMem + 1
      
      LinToBeSavedNames ((SelectMemN*0)+XSelectMem) = trim(adjustl(MemberName(XMem))) // " " &
      			// "model predictor"
      LinToBeSavedNames ((SelectMemN*1)+XSelectMem) = trim(adjustl(MemberName(XMem))) // " " &
      			// "model predictand"
      LinToBeSavedNames ((SelectMemN*2)+XSelectMem) = trim(adjustl(MemberName(XMem))) // " " &
      			// "scaled predictand"

      do XYear = 1, WorkYearN
        LinToBeSaved (((SelectMemN*0)+XSelectMem),XYear) = WorkActualExe   (XSelectMem,XYear)
        LinToBeSaved (((SelectMemN*1)+XSelectMem),XYear) = WorkActualWye   (XSelectMem,XYear)
        LinToBeSaved (((SelectMemN*2)+XSelectMem),XYear) = WorkPredictWye  (XSelectMem,XYear)
      end do
   end if 
end do
    
GaussChoice = 0
print*, "  > Save as raw (=1) or after 30y Gaussian filtering (=2) ?"
do
	read (*,*,iostat=ReadStatus), GaussChoice
	if (ReadStatus.LE.0.AND.GaussChoice.GE.1.AND.GaussChoice.LE.2) exit
end do
    
if (GaussChoice.EQ.2) then
    allocate (TempUnSmoo  (WorkYearN), &
              TempLowSmoo (WorkYearN), &
      	      TempHighSmoo(WorkYearN), stat=AllocStat)
    if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
      
    do XLine = 1, SaveLinN
        LinToBeSavedNames (XLine) = LinToBeSavedNames (XLine) // " 30GaussLow"
        
        TempUnSmoo   = MissVal
        TempLowSmoo  = MissVal
        TempHighSmoo = MissVal
        
        do XYear = 1, WorkYearN
          TempUnSmoo (XYear) = LinToBeSaved (XLine,XYear)
        end do
        
        call GaussSmooth (WorkYearN,30,TempUnSmoo,TempLowSmoo,TempHighSmoo)
        
        do XYear = 1, WorkYearN
          LinToBeSaved (XLine,XYear) = TempLowSmoo (XYear)
        end do        
    end do
      
    deallocate (TempUnSmoo,TempLowSmoo,TempHighSmoo)
end if
    
print*, "  > Enter the .lin file title (suggestions below): "
print*, " scale eq info : applic info "
print*, trim(adjustl(WorkGridTitle)) // " : run(s) : diagnostic : period : " &
    	    // " season : " // trim(adjustl(WorkRegTitle))    	    
do
	read (*,*,iostat=ReadStatus), SaveLinTitle
	if (ReadStatus.LE.0.AND.SaveLinTitle.NE."") exit
end do

call SaveLin (SaveLinN,WorkYearN,SaveLinTitle,LinToBeSavedNames,WorkADYear,LinToBeSaved)
    
deallocate (LinToBeSaved,LinToBeSavedNames,stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Deallocation failure #####"
    
print*, "  > Saved."

end subroutine ActualSaveRegion

!*******************************************************************************
! calc nat var of current ensemble

subroutine PrepareCalcNatVar

allocate (MemKey(WorkMemN),stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Deallocation failure #####"
MemKey     = 0
SelectMemN = 0

if (WorkMemN.GT.1) then
  print*, "  > Enter the members for which to calc nat var stats (99=exit): "
  do
	read (*,*,iostat=ReadStatus), SelectMem
	if (ReadStatus.LE.0.AND.SelectMem.GE.1.AND.SelectMem.LE.WorkMemN) &
		MemKey (SelectMem) = 1
	if (ReadStatus.LE.0.AND.SelectMem.EQ.99) exit
  end do
else
  MemKey (1) = 1
end if

do XMem = 1, WorkMemN
  if (MemKey(XMem).EQ.1) SelectMemN = SelectMemN + 1
end do

print*, "  > Predict using 30y slices ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), QEnsSlice
	if (ReadStatus.LE.0 .AND. QEnsSlice.GE.1.AND.QEnsSlice.LE.2) exit
end do

print*, "  > Preparing to calculate natural variability statistics..."

allocate (WorkAllPredict (WorkRegN,SelectMemN,WorkYearN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
WorkAllPredict = MissVal

XSelectMem = 0
do XMem = 1, WorkMemN		! load up predictor
 if (MemKey(XMem).EQ.1) then

  XSelectMem = XSelectMem + 1

  do XReg = 1, WorkRegN
   do XYear = 1, WorkYearN
    WorkAllPredict (XReg,XSelectMem,XYear) = WorkPredictand (XReg,XMem,XYear)
   end do
  end do
  
 end if
end do

if (QEnsSlice.EQ.2) then
 allocate (WorkOutExe(SelectMemN,WorkYearN), &
  	   WorkInExe (WorkYearN),            stat=AllocStat)
 if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
 
 do XReg = 1, WorkRegN 
  do XMem = 1, SelectMemN

   do XYear = 1, WorkYearN
    WorkOutExe (1,XYear) = WorkAllPredict (XReg,XMem,XYear)
   end do
   WorkInExe = MissVal
   
   call Sliceify (1,WorkYearN,30,WorkMissAccept,WorkOutExe,WorkInExe)
   
   do XYear = 1, WorkYearN
    WorkAllPredict (XReg,XMem,XYear) = WorkInExe (XYear)
   end do
  
  end do
 end do

 deallocate (WorkOutExe,WorkInExe)
end if
    
allocate (WorkSpaceABR (6,WorkRegN),    &
          WorkSpaceA   (WorkRegN), 	&
  	  WorkTimeABR  (6,WorkYearN),   stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

WorkSpaceABR = MissVal
WorkTimeABR  = MissVal

end subroutine PrepareCalcNatVar

!*******************************************************************************
! saves nat var stats

subroutine SaveNatVar

print*, "  > Save globally averaged stats to .lin ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SaveTimeABR
	if (ReadStatus.LE.0.AND.SaveTimeABR.GE.1.AND.SaveTimeABR.LE.2) exit
end do

if (SaveTimeABR.EQ.2) then
  print*, "  > Enter the .lin file title: "
  do
	read (*,*,iostat=ReadStatus), SaveLinTitle
	if (ReadStatus.LE.0.AND.SaveLinTitle.NE."") exit
  end do
  
  allocate (LinToBeSavedNames (6), stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"
  LinToBeSavedNames(1) = "global LSR 'a' y=ax+b : min"
  LinToBeSavedNames(2) = "global LSR 'a' y=ax+b : max"
  LinToBeSavedNames(3) = "global LSR 'b' y=ax+b : min"
  LinToBeSavedNames(4) = "global LSR 'b' y=ax+b : min"
  LinToBeSavedNames(5) = "global Pearson coeff  : min"
  LinToBeSavedNames(6) = "global Pearson coeff  : max"
  
  call SaveLin (6,WorkYearN,SaveLinTitle,LinToBeSavedNames,WorkADYear,WorkTimeABR)
  
  deallocate (LinToBeSavedNames)
end if


print*, "  > Auto-save regionally av LSR stats (y=ax+b) to 6 * .glo ? (1=no,2=yes)"
do
	read (*,*,iostat=ReadStatus), SaveSpaceA
	if (ReadStatus.LE.0.AND.SaveSpaceA.GE.1.AND.SaveSpaceA.LE.2) exit
end do

if (SaveSpaceA.EQ.2) then
  print*, "  > Enter the generic .glo file title: "
  do
	read (*,*,iostat=ReadStatus), WorkGloTitle
	if (ReadStatus.LE.0.AND.WorkGloTitle.NE."") exit
  end do
  
  do XGloFile = 1, 6
    print*, "  > File to be saved includes: "
    if (XGloFile.EQ.1.OR.XGloFile.EQ.2) print*, "  > y=ax+b : a"
    if (XGloFile.EQ.3.OR.XGloFile.EQ.4) print*, "  > y=ax+b : b"
    if (XGloFile.EQ.5.OR.XGloFile.EQ.6) print*, "  > y=ax+b : r"
    if (XGloFile.EQ.1.OR.XGloFile.EQ.3.OR.XGloFile.EQ.5) print*, "  > ensemble min values"
    if (XGloFile.EQ.2.OR.XGloFile.EQ.4.OR.XGloFile.EQ.6) print*, "  > ensemble max values"
      
    do XReg = 1, WorkRegN
      WorkSpaceA (XReg) = WorkSpaceABR (XGloFile,XReg)
    end do
  
    call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGloTitle,WorkGridFilePath, &
	          WorkSpaceA,WorkMapIDLReg)
  end do
end if

end subroutine SaveNatVar

!*******************************************************************************
! calcs nat var stats

subroutine CalcNatVar

call PrepareCalcNatVar

print*, "  > Calculating spatially-varying correlations..."

allocate (WorkOutExe (1,WorkYearN), &
	  WorkOutWye (1,WorkYearN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

do XReg = 1, WorkRegN		! calc spatially-varying corr
  do XPredictor = 1, SelectMemN
   do XPredictand = 1, SelectMemN
    if (XPredictor.NE.XPredictand) then
     
     do XYear = 1, WorkYearN
      WorkOutExe (1,XYear) = WorkAllPredict (XReg,XPredictor, XYear)
      WorkOutWye (1,XYear) = WorkAllPredict (XReg,XPredictand,XYear)
     end do

     call LinearLSR (1,WorkYearN,WorkOutExe,WorkOutWye,LSRAye,LSRBee,LSRPea)
     
     if (LSRAye.NE.MissVal) then
       if (WorkSpaceABR(1,XReg).EQ.MissVal) WorkSpaceABR(1,XReg) = LSRAye
       if (WorkSpaceABR(2,XReg).EQ.MissVal) WorkSpaceABR(2,XReg) = LSRAye
       if (WorkSpaceABR(1,XReg).GT.LSRAye)  WorkSpaceABR(1,XReg) = LSRAye
       if (WorkSpaceABR(2,XReg).LT.LSRAye)  WorkSpaceABR(2,XReg) = LSRAye
     end if
     
     if (LSRBee.NE.MissVal) then
       if (WorkSpaceABR(3,XReg).EQ.MissVal) WorkSpaceABR(3,XReg) = LSRBee
       if (WorkSpaceABR(4,XReg).EQ.MissVal) WorkSpaceABR(4,XReg) = LSRBee
       if (WorkSpaceABR(3,XReg).GT.LSRBee)  WorkSpaceABR(3,XReg) = LSRBee
       if (WorkSpaceABR(4,XReg).LT.LSRBee)  WorkSpaceABR(4,XReg) = LSRBee
     end if
     
     if (LSRPea.NE.MissVal) then
       if (WorkSpaceABR(5,XReg).EQ.MissVal) WorkSpaceABR(5,XReg) = LSRPea
       if (WorkSpaceABR(6,XReg).EQ.MissVal) WorkSpaceABR(6,XReg) = LSRPea
       if (WorkSpaceABR(5,XReg).GT.LSRPea)  WorkSpaceABR(5,XReg) = LSRPea
       if (WorkSpaceABR(6,XReg).LT.LSRPea)  WorkSpaceABR(6,XReg) = LSRPea
     end if
     
    end if
   end do
  end do
end do

deallocate (WorkOutExe,WorkOutWye)

print*, "  > Calculating temporally-varying correlations..."

allocate (WorkOutExe (1,WorkRegN), &
	  WorkOutWye (1,WorkRegN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Allocation failure #####"

do XYear = 1, WorkYearN		! calc temporally-varying corr
  do XPredictor = 1, SelectMemN
   do XPredictand = 1, SelectMemN
    if (XPredictor.NE.XPredictand) then

     do XReg = 1, WorkRegN
      WorkOutExe (1,XReg) = WorkAllPredict (XReg,XPredictor, XYear)
      WorkOutWye (1,XReg) = WorkAllPredict (XReg,XPredictand,XYear)
     end do

     call LinearLSR (1,WorkYearN,WorkOutExe,WorkOutWye,LSRAye,LSRBee,LSRPea)
     
     if (LSRAye.NE.MissVal) then
       if (WorkTimeABR(1,XYear).EQ.MissVal) WorkTimeABR(1,XYear) = LSRAye
       if (WorkTimeABR(2,XYear).EQ.MissVal) WorkTimeABR(2,XYear) = LSRAye
       if (WorkTimeABR(1,XYear).GT.LSRAye)  WorkTimeABR(1,XYear) = LSRAye
       if (WorkTimeABR(2,XYear).LT.LSRAye)  WorkTimeABR(2,XYear) = LSRAye
     end if
     
     if (LSRBee.NE.MissVal) then
       if (WorkTimeABR(3,XYear).EQ.MissVal) WorkTimeABR(3,XYear) = LSRBee
       if (WorkTimeABR(4,XYear).EQ.MissVal) WorkTimeABR(4,XYear) = LSRBee
       if (WorkTimeABR(3,XYear).GT.LSRBee)  WorkTimeABR(3,XYear) = LSRBee
       if (WorkTimeABR(4,XYear).LT.LSRBee)  WorkTimeABR(4,XYear) = LSRBee
     end if
     
     if (LSRPea.NE.MissVal) then
       if (WorkTimeABR(5,XYear).EQ.MissVal) WorkTimeABR(5,XYear) = LSRPea
       if (WorkTimeABR(6,XYear).EQ.MissVal) WorkTimeABR(6,XYear) = LSRPea
       if (WorkTimeABR(5,XYear).GT.LSRPea)  WorkTimeABR(5,XYear) = LSRPea
       if (WorkTimeABR(6,XYear).LT.LSRPea)  WorkTimeABR(6,XYear) = LSRPea
     end if
     
    end if
   end do
  end do
end do

deallocate (WorkOutExe,WorkOutWye,WorkAllPredict)

call SaveNatVar

deallocate (MemKey,WorkSpaceABR,WorkTimeABR,WorkSpaceA)

end subroutine CalcNatVar

!*******************************************************************************
! close operations down

subroutine WindDown

if (AyeActive.EQ.1) then
  deallocate (WorkRegAye, stat=AllocStat)
  if (AllocStat.EQ.0) AyeActive = 0
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Deallocation failure #####"
end if

if (PredictActive.EQ.1) then
  deallocate (WorkPredictor,WorkPredictand,stat=AllocStat)
  if (AllocStat.EQ.0) PredictActive = 0
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Deallocation failure #####"
end if

deallocate (TimRegNames,stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: WindDown: Deallocation failure #####"

print*

end subroutine WindDown

!*******************************************************************************

end program ScaleOps
