! perbulk.f90
! program to handle .per files in bulk
! pgf90 -Mstandard -Minfo -fast -Mscalarsse -Mvect=sse -Mflushz 
! 	-o ./../obs/perbulk time.f90 filenames.f90 perfiles.f90 annfiles.f90 
!	plainperm.f90 regress.f90 
! 	cetgeneral.f90 ./../obs/perbulk.f90 2> /tyn1/tim/scratch/stderr.txt
! last modified on 13.03.02

program PerBulk

use Time
use FileNames
use PerFiles
use AnnFiles
use Regress
use CETGeneral

implicit none

real, pointer, dimension (:,:)			:: InMon, InSea, OutDec, OutAll, LSRAye, LSRBee
real, pointer, dimension (:)			:: InAnn, LSRExe, LSRWye, VecA,VecB,VecC

integer, pointer, dimension (:) 		:: YearAD

character (len=80), pointer, dimension (:) 	:: InFileA, InFileB, OutFileA, FileNameOnly
character (len= 9), pointer, dimension(:)	:: ColTitles			! can be 'X', no blanks

real, parameter :: MissVal = -999.0

character (len=80), parameter :: Blank = ""

real :: OpTot, OpEn, OpMiss, BaseTot, BaseEn
real :: LSRPea

integer :: ReadStatus, AllocStat
integer :: MenuChoice, FileVariCode
integer :: FileN, FileYearN, YearN
integer :: XFile, XFileYear, XYear, XMonth, XSeason, XDecade, XAnnual, XDecadeYear, XBegYear, XBegDecade
integer :: BegYearAD, Silent, SmooPer
integer :: InSubLen,InSubBeg,InFileALen,LastSlash,OutSubBeg,StatType,NameEnd
integer :: QVariTime,QLSRForm,QMissCalc

character (len=80) :: GivenFile, NameOnly
character (len=80) :: InSub, OutSub

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

call Intro
call Menu
call Final

contains

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

subroutine Intro

open (99,file="/tyn1/tim/scratch/log-perbulk.dat",status="replace",action="write")
print*
print*, "  > ***** PerBulk.f90 : handles .per files in bulk *****"
print*

end subroutine Intro

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

subroutine Menu

MenuChoice = 0
do
  print*, "  > MENU: make your choice (0=list):"
  do
	read (*,*,iostat=ReadStatus), MenuChoice
	if (ReadStatus.LE.0) exit
  end do
  
  if      (MenuChoice.EQ. 0) then
    print*, "  > 10. save InAnn OutDec means"
    print*, "  > 20. regression: y=at or y=at+b"
    print*, "  > 30. smooth with Gaussian filter"
    print*, "  > 99. end"    
  else if (MenuChoice.EQ.10) then
    call SaveAnnDecMeans
  else if (MenuChoice.EQ.20) then
    call RegressionYATB
  else if (MenuChoice.EQ.30) then
    call SmoothGaussFilter
  else if (MenuChoice.EQ.99) then
    print*
  else
    print*, "  > Pardon ?"
  end if
  
  if (MenuChoice.EQ.99) exit
end do

end subroutine Menu

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

subroutine SaveAnnDecMeans

print*, "  > Select the OLD files. There must be a common substring."
call GetBatch (Blank,InFileA)
FileN = size (InFileA, 1)

call GetOutFileA
do XFile = 1, FileN
  GivenFile = OutFileA(XFile)
  OutSubBeg = index(GivenFile,'.per')
  if (OutSubBeg.GT.0) OutFileA(XFile) = GivenFile(1:(OutSubBeg-1)) // ".ann"
end do

print*, "  > Select the year AD to begin to calc: "
do
	read (*,*,iostat=ReadStatus), BegYearAD
	if (ReadStatus.LE.0) exit
end do

do XFile = 1, FileN
  GivenFile = InFileA(XFile)
  LastSlash = index(GivenFile,"/",.TRUE.)
  NameOnly  = adjustl(trim(GivenFile((LastSlash+1):80)))
  print*
  print "(a,i4,2a)", "   > Batch item: ", XFile, ": ", trim(NameOnly)
  
  call LoadPer (InFileA(XFile), FileVariCode, YearAD, InMon, InSea, InAnn)
  deallocate (InMon, InSea)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: PerBulk: MonSea: Deallocation failure #####"

  FileYearN = size (YearAD,1)
  
  allocate (OutDec (FileYearN,5), &
	    ColTitles (5),         stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: PerBulk: OutDec: Allocation failure #####"
  OutDec = MissVal
  ColTitles = (/'  ann tot',' dec anom',' dec mean',' no years','  missing'/)

  XFileYear = 0 ; XBegYear = 0 ; XDecadeYear = 0 ; XDecade = 0
  OpTot = 0.0 ; OpEn = 0.0 ; OpMiss = 0.0 ; BaseTot = 0.0 ; BaseEn = 0.0
  do
    XFileYear = XFileYear + 1
    if (InAnn(XFileYear).NE.MissVal) OutDec(XFileYear,1) = InAnn(XFileYear)
    
    if (YearAD(XFileYear).EQ.BegYearAD) XBegYear = XFileYear
        
    if (XBegYear.GT.0) then
      XDecadeYear = XDecadeYear + 1      
      if (InAnn(XFileYear).NE.MissVal) then
        OpTot = OpTot + InAnn(XFileYear)
        OpEn  = OpEn  + 1
      else
        OpMiss = OpMiss + 1
        OpEn   = OpEn   + 1
      end if
    end if
    
    if (XDecadeYear.EQ.10.OR.XFileYear.EQ.FileYearN) then
      XDecade = XDecade + 1
      XBegDecade = XBegYear + ((XDecade-1)*10)
      
      if (OpEn.GT.0) then
        OutDec (XBegDecade,3) = OpTot / OpEn
        OutDec (XBegDecade,4) = OpEn
        OutDec (XBegDecade,5) = OpMiss
      end if
      
      XDecadeYear = 0 ; OpTot = 0.0 ; OpEn = 0.0 ; OpMiss = 0.0
    end if
    
    if (YearAD(XFileYear).GE.1961.AND.YearAD(XFileYear).LE.1990) then
      if (InAnn(XFileYear).NE.MissVal) then
        BaseTot = BaseTot + InAnn(XFileYear)
        BaseEn  = BaseEn  + 1
      end if
    end if
    
    if (XFileYear.EQ.FileYearN) exit
  end do
  
  if (BaseEn.GE.10) then
    do XFileYear = 1, FileYearN
      if (OutDec(XFileYear,3).NE.MissVal) OutDec(XFileYear,2) = OutDec(XFileYear,3) - (BaseTot/BaseEn)
    end do
  end if
  
  call SaveANN (OutFileA(XFile), YearAD, ColTitles, OutDec, DecPlaceN=1)

  deallocate (InAnn, YearAD, OutDec, ColTitles)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: PerBulk: AnnYAD: Deallocation failure #####"
end do

deallocate (InFileA,OutFileA)
if (AllocStat.NE.0) print*, "  > ##### ERROR: PerBulk: DecInOut: Deallocation failure #####"

end subroutine SaveAnnDecMeans

!*******************************************************************************
! regress y=at+b: inB = (outA * inA) + outB

subroutine RegressionYATB

print*, "  > Regression form: y=at (=1) or y=at+b (=2) ?" 
do
	read (*,*,iostat=ReadStatus), QLSRForm
	if (ReadStatus.LE.0.AND.QLSRForm.GE.1.AND.QLSRForm.LE.2) exit
end do
  
print*, "  > Select the 'y' files. There must be a common substring."
call GetBatch (Blank,InFileA)
FileN = size (InFileA, 1)

allocate (LSRAye (FileN,17), &
  	  LSRBee (FileN,17), &
  	  FileNameOnly (FileN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: PerBulk: RegressionYATB: Allocation failure: A,B #####"
LSRAye = MissVal ; LSRBee = MissVal

print*, "  > Operating in bulk..."
do XFile = 1, FileN
  GivenFile = InFileA(XFile)
  LastSlash = index(GivenFile,"/",.TRUE.)
  FileNameOnly(XFile)  = adjustl(trim(GivenFile((LastSlash+1):80)))
  
  call LoadPer (InFileA(XFile), FileVariCode, YearAD, InMon, InSea, InAnn, Silent=1)  
  FileYearN = size (YearAD,1)
  
  allocate (LSRExe (FileYearN), &
  	    LSRWye (FileYearN), stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: PerBulk: RegressionYATB: Allocation failure: X,Y #####"
  
  do XYear = 1, FileYearN
      LSRExe (XYear) = YearAD (XYear)
  end do

  do XMonth = 1, 12
    do XYear = 1, FileYearN
      LSRWye (XYear) = InMon (XYear,XMonth)
    end do
    
    if (QLSRForm.EQ.1) then
      call LinearLSRZeroVec (LSRWye,LSRExe,LSRAye(XFile,XMonth))
    else
      call LinearLSRVec (LSRWye,LSRExe,LSRBee(XFile,XMonth),LSRAye(XFile,XMonth),LSRPea)
    end if
  end do
  
  do XSeason = 1, 4
    do XYear = 1, FileYearN
      LSRWye (XYear) = InSea (XYear,XSeason)
    end do
    
    if (QLSRForm.EQ.1) then
      call LinearLSRZeroVec (LSRWye,LSRExe,LSRAye(XFile,(XSeason+12)))
    else
      call LinearLSRVec (LSRWye,LSRExe,LSRBee(XFile,(XSeason+12)),LSRAye(XFile,(XSeason+12)),LSRPea)
    end if
  end do
  
  do XYear = 1, FileYearN
      LSRWye (XYear) = InAnn (XYear)
  end do
    
  if (QLSRForm.EQ.1) then
      call LinearLSRZeroVec (LSRWye,LSRExe,LSRAye(XFile,17))
  else
      call LinearLSRVec (LSRWye,LSRExe,LSRBee(XFile,17),LSRAye(XFile,17),LSRPea)
  end if
  
  deallocate (LSRExe,LSRWye, stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: PerBulk: RegressionYATB: Deallocation failure: X,Y #####"  

								!###########################
  write (99,"(a20,17e12.5)"), trim(FileNameOnly(XFile)), (LSRAye(XFile,XSeason),XSeason=1,17)
end do

write (99,*), "GRADIENTS  (12*mon,4*sea,1*ann)"
do XFile = 1, FileN
  write (99,"(a20,17e12.5)"), trim(FileNameOnly(XFile)), (LSRAye(XFile,XSeason),XSeason=1,17)
end do

if (QLSRForm.EQ.2) then
 write (99,*), "INTERCEPTS (12*mon,4*sea,1*ann)"
 do XFile = 1, FileN
  write (99,"(a20,17e12.5)"), trim(FileNameOnly(XFile)), (LSRBee(XFile,XSeason),XSeason=1,17)
 end do
end if

print*, "  > We have dumped the results to log file."

end subroutine RegressionYATB

!*******************************************************************************
! smooth with Gaussian filter

subroutine SmoothGaussFilter

print*, "  > Select the OLD files. There must be a common substring."
call GetBatch (Blank,InFileA)
FileN = size (InFileA, 1)

call GetOutFileA

print*, "  > Select the period at which to smooth: "
do
	read (*,*,iostat=ReadStatus), SmooPer
	if (ReadStatus.LE.0.AND.SmooPer.GE.1) exit
end do

print*, "  > Keep missing seas/ann (=1), or calc from interpol monthly (=2) ?"
do
	read (*,*,iostat=ReadStatus), QMissCalc
	if (ReadStatus.LE.0.AND.QMissCalc.GE.1.AND.QMissCalc.LE.2) exit
end do

print*, "  > Enter the statistic (-1=min,0=mean,1=max,2=sum): "
do
	read (*,*,iostat=ReadStatus), StatType
	if (ReadStatus.LE.0.AND.StatType.GE.-1.AND.StatType.LE.2) exit
end do

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

do XFile = 1, FileN
 call LoadPer (InFileA(XFile), FileVariCode, YearAD, InMon, InSea, InAnn, Silent=1)  
 
 GivenFile = InFileA(XFile)
 LastSlash = index(GivenFile,"/",.TRUE.)
 NameEnd = index(GivenFile,".per",.TRUE.) ; NameEnd=NameEnd+3
 NameOnly  = trim(GivenFile((LastSlash+1):NameEnd))
  
 YearN = size (YearAD,1)
  
 if (YearN.GT.SmooPer) then
  print "(2a)", "   > Smoothing ", trim(NameOnly)
  
  allocate (VecA(YearN), &
  	    VecB(YearN), &
  	    VecC(YearN), &
  	    OutAll(YearN,17), stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: SmoothGaussFilter: Allocation failure: Vec* #####"
 
  do XMonth = 1, 12
    VecA=MissVal ; VecB=MissVal ; VecC=MissVal
    
    do XYear = 1, YearN
      VecA(XYear) = InMon(XYear,XMonth)
    end do
    
    call GaussSmooth (YearN,SmooPer,1,VecA,VecB,VecC,MissThresh=20.0)
    
    do XYear = 1, YearN
      OutAll(XYear,XMonth) = VecB(XYear)
      if (InMon(XYear,XMonth).EQ.MissVal) InMon(XYear,XMonth) = VecB(XYear)
    end do
  end do
  
  if (QMissCalc.EQ.2) then
    InSea=MissVal ; InAnn=MissVal
    
    if (StatType.EQ.-1) call FillSeaAnnMin  (YearAD,InMon,InSea,InAnn)
    if (StatType.EQ. 0) call FillSeaAnnMean (YearAD,InMon,InSea,InAnn)
    if (StatType.EQ. 1) call FillSeaAnnMax  (YearAD,InMon,InSea,InAnn)
    if (StatType.EQ. 2) call FillSeaAnnSum  (YearAD,InMon,InSea,InAnn)  
  end if
  
  do XSeason = 1, 4
    VecA=MissVal ; VecB=MissVal ; VecC=MissVal
    
    do XYear = 1, YearN
      VecA(XYear) = InSea(XYear,XSeason)
    end do
    
    call GaussSmooth (YearN,SmooPer,1,VecA,VecB,VecC,MissThresh=20.0)
    
    do XYear = 1, YearN
      OutAll(XYear,(XSeason+12)) = VecB(XYear)
    end do
  end do
  
  do XAnnual = 1, 1
    VecA=MissVal ; VecB=MissVal ; VecC=MissVal
    
    do XYear = 1, YearN
      VecA(XYear) = InAnn(XYear)
    end do
    
    call GaussSmooth (YearN,SmooPer,1,VecA,VecB,VecC,MissThresh=20.0)
    
    do XYear = 1, YearN
      OutAll(XYear,17) = VecB(XYear)
    end do
  end do
  
  call SavePER (OutFileA(XFile), YearAD, StatType, AllData=OutAll, NoResponse=1)
  
  deallocate (VecA,VecB,VecC,stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: SmoothGaussFilter: Deallocation failure: Vec* #####"
 else
  print "(3a)", "   > Rejecting ", trim(NameOnly), " due to short record."
 end if
  
 deallocate (InMon,InSea,InAnn,YearAD,stat=AllocStat)
 if (AllocStat.NE.0) print*, "  > ##### ERROR: SmoothGaussFilter: Deallocation failure: In* #####"
end do

end subroutine SmoothGaussFilter

!*******************************************************************************
! get output file vector

subroutine GetOutFileA

print*, "  > Enter the substring in the OLD files to alter in the NEW files: "
do
	read (*,*,iostat=ReadStatus), InSub
	if (ReadStatus.GT.0) then	
			print*, "  > Bad format. Try again."
	else if (InSub.EQ."") then
			print*, "  > Blank not permitted. Try again."
	end if
	if (ReadStatus.LE.0.AND.InSub.NE."") exit
end do

print "(3a)", "   > Enter the substring in the NEW files to replace '", trim(InSub), "':"
do
	read (*,*,iostat=ReadStatus), OutSub
	if (ReadStatus.GT.0) then	
			print*, "  > Bad format. Try again."
	else if (OutSub.EQ."") then
			print*, "  > Blank not permitted. Try again."
	end if
	if (ReadStatus.LE.0.AND.OutSub.NE."") exit
end do

InSubLen = len(trim(InSub))
  
allocate (OutFileA (FileN), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: PerBulk: OutFileA: Allocation failure #####"
OutFileA = ""

do XFile = 1, FileN
      GivenFile = InFileA(XFile)
      InSubBeg  = index(GivenFile,trim(InSub))
      InFileALen = len(trim(GivenFile))
      
      OutFileA(XFile) = GivenFile(1:(InSubBeg-1)) // trim(OutSub) // &
      		GivenFile((InSubBeg+InSubLen):InFileALen)
end do

end subroutine GetOutFileA

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

subroutine Final

close (99)

end subroutine Final

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

end program PerBulk
