! homogiter.f90
! pgf90 -Mstandard -Minfo -fast -Mscalarsse -Mvect=sse -Mflushz 
!	-o ./../cruts/homogiter time.f90 filenames.f90 crutsfiles.f90 
!	perfiles.f90 cetgeneral.f90 gridops.f90 sortmod.f90 plainperm.f90 regress.f90 
!	fdist_k.f90 fdist_br.f90 fdist.f90 ttest.f90 ghcnrefiter.f90 ghcndiscon.f90 
!	./../cruts/homogiter.f90 2> /tyn1/tim/scratch/stderr.txt

program Homogiter

use Time
use FileNames
use CRUtsFiles
use PerFiles
use CETGeneral
use GridOps
use SortMod
use PlainPerm
use Regress
use FDist_K
use FDist_BR
use FDist
use TTest
use GHCNrefIter
use GHCNdiscon

implicit none

logical, pointer, dimension (:,:)	:: Disc,DiscCrude,Trust,Believe,Got,Need
logical, pointer, dimension (:)		:: Examine,Sought,GotRef

real, pointer, dimension (:,:)		:: AdjMon,AdjSea
real, pointer, dimension (:)		:: OLat,OLon,OElv, AdjStn,AdjAnn
real, pointer, dimension (:)		:: Lat,Lon,Elv, DLat,DLon,DElv

integer, pointer, dimension (:,:,:)	:: Data,DData,OData,PData,RefTS,DumpTarget,Adj
integer, pointer, dimension (:,:,:)	:: DataSrc,ODataSrc,AdjSrc
integer, pointer, dimension (:,:)	:: Info,DInfo,OInfo,DNormals,TrashInfo
integer, pointer, dimension (:)		:: YearAD,DYearAD,PYearAD,TrashYearAD
integer, pointer, dimension (:)		:: Code,OCode,DCode,PCode,Order,OldCode,OOldCode
integer, pointer, dimension (:)		:: EarlBeg,EarlEnd,LateBeg,LateEnd,ThisBeg,ThisEnd
integer, allocatable, dimension (:)	:: StnLen
integer, dimension (12)			:: Climatology,DumpData

character (len=80), pointer, dimension (:) :: Batch
character (len=20), pointer, dimension (:) :: Name,DName,OName,TrashName
character (len=13), pointer, dimension (:) :: Cty,DCty,OCty,TrashCty
character (len=09), pointer, dimension (:) :: Local,DLocal,OLocal,TrashLocal

real, parameter 	:: Missval = -999.0
integer, parameter 	:: DataMissval = -9999

logical :: Verbose,PlotAllManip,Differ,Plotted,QBlank,Match,Clash,ForceLate

real :: Aye,Bee,Enn,Are,Pea,Decay,TTestResult,OpTot,OpEn,OpMean,OpWin,OpAdd,OpValid
real :: OpOData,OpRefTS,OpAdj,OpClim
real :: PlotThresh,Req,LatTot,LonTot,DistTot,DistTotSq,Dist,DistMax
real :: CentroidLat,CentroidLon,CentroidRange, BoxLatDeg,BoxLonDeg
real :: RealTarget,RealClim,RealOData,RealRefTS,RealAdj

integer :: AllocStat,ReadStatus, Beg,End,DBeg,DEnd,KBeg,KEnd,PBeg,PEnd
integer :: Dropped,IterInt,Omit,ExtraTerm
integer :: QDump,QAbs,QAnom,QStep,QDumpView,QOneCont,QUseDStn
integer :: QCountOnly,QType,QRetry
integer :: NYear,NDYear,NMonth,NStn,NDStn,NOStn,NIterate,NDisc,NTrust,NGotRef,NSought
integer :: XYear,XDYear,XMonth,XStn,XDStn,XOstn,XIterate,XDisc,XTrust,XGotRef,XSought
integer :: NBatch,NInfo,NWindow,NMiss,NExam,NOYear,NLat,NLon,NGot,NNeed,NPYear,NPStn
integer :: XBatch,XInfo,XWindow,XMiss,XExam,XOYear,XLat,XLon,XGot,XNeed,XPYear,XPStn
integer :: BegO,EndO,BegR,EndR, SubBeg,SubLen, Log0,Log1,LogAdj,LogNon, OBeg,OEnd
integer :: OuterLen,Elastic

character (len=99) :: Command
character (len=80) :: DataFile,DatabaseFile,Title,GivenFile,DumpFile,PerFile,HdrFile
character (len=80) :: DataSrcFile,SaveSrcFile,SaveFileOne,SaveFileTwo,ParallelFile
character (len=20) :: String20,IterStr,CallForm
character (len=10) :: FileTime
character (len= 8) :: StnText,DumpText,FileDate,FileText
character (len= 7) :: ScreenText
character (len= 4) :: IterText,VariableSuffix

call Main

contains

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

subroutine Main

call Initialise
call SpecifyCommon

print*, "  > Loading..."
if (DatabaseFile.NE."none") then
  call LoadDatabase
else
  call LoadDatabaseDummy
end if  
call LoadOriginal
call GetCoverage

QCountOnly=1 ; NStn=NOStn ; call Screen
call SpecComb
QcountOnly=0 ; XStn=NOStn ; call Screen
call MakeArrays
if (QRetry.GT.0) call LoadParallel

call Process
call SaveTwo

if      (QDumpView.EQ.1) then
  print*, "  > Plotting stns with discon..."
  call PlotDiscStn
else if (QDumpView.EQ.2) then
  print*, "  > Dumping stns with discon..."
  call DumpDiscStn
end if

if (ExtraTerm.EQ.1) call system ('printf "end" >> ./../../../scratch/f90toidl.pipe')
print*
close (99)

end subroutine Main

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

subroutine Process

print*, "  > Processing..."
write (99,"(i4,a,i4)"), YearAD(1), "-", YearAD(NYear)
do XStn=1,NStn
  write (99,"(i4,x,a20,x,a13,2f8.2)"), XStn,Name(XStn),Cty(XStn),Lat(XStn),Lon(XStn)
end do

call MakeRefTS (RefTS,Data,Lat,Lon,Sought,Trust,Decay,Differ, &
  			.FALSE.,nint(MissVal),GotRef)
call Trustworthy (Data,RefTS,Sought,Trust)	! ghcnrefiter.f90
call MakeContinuous (Data,RefTS,Sought,DiscCrude,YearAD,Differ,Verbose)

NGotRef=count(GotRef) ; NSought=NOStn ; NDisc=count(DiscCrude)
OuterLen=maxval(StnLen,Sought)
print "(a,4a7)", "   > ITERATIONS (iter gaps)","    GOT","  TO-DO","  DISCS"," MAXLEN"
print "(a,4i7)", "   > readied               ",NGotRef,NSought,NDisc,OuterLen

Omit=0 ; XIterate=0 ; RefTS=DataMissVal ; ForceLate=.TRUE.
do			! MAIN ITERATION LOOP
  XIterate=XIterate+1			! calc quality ref ts, but with restrictions
  
  if (ForceLate) then
    call MakeRefTS (RefTS,Data,Lat,Lon,Sought,Trust,Decay,Differ, &
  		.TRUE.,Omit,GotRef,Disc=DiscCrude, &
		ForceBeg=LateBeg,ForceEnd=LateEnd,MakeMore=.TRUE.)
  else
    call MakeRefTS (RefTS,Data,Lat,Lon,Sought,Trust,Decay,Differ, &
  		.TRUE.,Omit,GotRef,Disc=DiscCrude, &
		ForceBeg=EarlBeg,ForceEnd=EarlEnd,MakeMore=.TRUE.)
  end if
  
  NGotRef=count(GotRef) ; NSought=NSought-NGotRef 
  if (count(DiscCrude).NE.NDisc) print*, "  > @@@@@ ERROR: Disc error @@@@@" 
  write (99,"(a,2i4,3i7)"), "CHECK",XIterate,Omit,NGotRef,NSought,NDisc
  
  if (NGotRef.GT.0) then	! have got more stns with ref ts
    					! for these stns, correct original Data
    call MakeContinuous (Data,RefTS,GotRef,Disc,YearAD,Differ,Verbose,Adj=Data)
    					! ... and make checked part trusted
    call Trustworthy    (Data,RefTS,GotRef,Believe)
	
    do XStn=1,NStn
      if (GotRef(XStn)) then		! stn has ref ts
        Sought(XStn)=.FALSE.		! so no longer needs checking
        
	do XYear=1,NYear
          if (Believe(XYear,XStn)) then	! for the years with a valid ref ts
	    Trust(NYear,NStn)=.TRUE.	! the series may enter other ref ts
	    if (DiscCrude(XYear,XStn)) then
              DiscCrude(XYear,XStn)=.FALSE.	! any discon have been healed	
              NDisc=NDisc-1
            end if
	  end if
        end do
      end if
    end do
  
    if (ForceLate) then
      ForceLate=.FALSE.
    else
      ForceLate=.TRUE.
    end if
    
    ScreenText="checked"
    print "(2a,2(a,i4),a,4i7)", "   > ", ScreenText, "    (", &	
    		XIterate,",",Omit,")",NGotRef,NSought,NDisc,OuterLen
  else
    Omit=Omit+5				! relax restrictions one notch
    ForceLate=.TRUE.
  
    do XStn=1,NStn
      if (Sought(XStn)) then
        if ((StnLen(XStn)-Omit).LE.(2*Elastic)) then
          Sought(XStn)=.FALSE. ; NSought=NSought-1
        end if
      end if
    end do
    
    ScreenText="relaxed" ; NGotRef=MissVal
  end if
  
  if (NSought.GT.0) then
      OuterLen=maxval(StnLen,Sought)
  else
      OuterLen=0
  end if
    
  if (NSought.EQ.0.OR.Omit.GE.OuterLen) exit
end do

allocate (Adj(NYear,NMonth,NStn),AdjMon(NYear,NMonth),AdjStn(NStn),stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### Process: alloc Adj* #####"
Adj=DataMissVal ; AdjMon=MissVal ; AdjStn=MissVal

call FilterOrig (Data,RefTS,Adj,Examine,Differ)
call MeasureAdjAll (OData,Adj,RefTS,AdjMon,AdjStn,Examine)

end subroutine Process

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

subroutine Initialise

open (99,file="./../../../scratch/log-homogiter.dat", &
		status="replace",action="write")

print*
print*, "  > ***** Homogiter: homogenises new stn files *****"
print*, "  > cleanmeta.f90 must be run first, and outputs used here"
print*

NMonth=12

end subroutine Initialise

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

subroutine SpecifyCommon

print*, "  > Extra terminals (log,idl) ? (0=no,1=yes,2=dump) "
do
  read (*,*,iostat=ReadStatus), ExtraTerm
  if (ReadStatus.LE.0.AND.ExtraTerm.GE.0.AND.ExtraTerm.LE.2) exit
end do

if (ExtraTerm.EQ.1) then
  Command='xterm -iconic -geometry 90x20+500+0 -T log -e tail -f' // &
	' ./../../../scratch/log-homogenise.dat &'
  call system (Command)
  call system ('xterm -iconic -geometry 80x40+0+20 -T idl -e idl startup &')
end if

print*, "  > Select the .cts file to load: "
do
  read (*,*,iostat=ReadStatus), GivenFile
  if (ReadStatus.LE.0.AND.GivenFile.NE."") exit
end do
DataFile = LoadPath(GivenFile,".cts")
SubBeg = index(DataFile,".cts") - 4
VariableSuffix = DataFile(SubBeg:SubBeg+3)
QRetry = index(DataFile,"retry")

if (QRetry.GT.0) then
  SubBeg = index(DataFile,"/",.TRUE.) ; SubLen = len_trim(DataFile)
  DataFile((SubLen-8):(SubLen-8)) = "?"
  call GetBatch (DataFile,Batch,Silent=1) 
  NBatch=size(Batch) ; DataFile = Batch(NBatch)
  deallocate (Batch,stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### SpecifyCommon: dealloc: Batch #####"
  IterStr = DataFile((SubLen-8):(SubLen-8))
  IterInt = GetIntFromText (IterStr)
  IterInt = IterInt + 1
  IterStr = GetTextFromInt (IterInt)
  GivenFile = "./../../../data/cruts/homog" // DataFile(SubBeg:(SubLen-9)) &
  		// trim(adjustl(IterStr)) // DataFile((SubLen-7):SubLen)
else
  SubBeg = index(DataFile,"/",.TRUE.) ; SubLen = len_trim(DataFile)
  GivenFile = "./../../../data/cruts/homog" // DataFile(SubBeg:(SubLen-8)) &
  		// ".1" // DataFile((SubLen-7):SubLen)
end if

print "(2a)", "   > Save file: ", trim(GivenFile)
SaveFileTwo = SavePath (GivenFile,".cts")

if      (VariableSuffix.EQ.'.tmp') then
  Decay=1200.0 ; Differ=.TRUE. ; Elastic=5
else if (VariableSuffix.EQ.'.dtr') then
  Decay= 750.0 ; Differ=.TRUE. ; Elastic=5
else if (VariableSuffix.EQ.'.pre') then
  Decay= 450.0 ; Differ=.FALSE. ; Elastic=10
else if (VariableSuffix.EQ.'.vap') then
  Decay=1000.0 ; Differ=.TRUE. ; Elastic=5
else if (VariableSuffix.EQ.'.cld') then
  Decay= 600.0 ; Differ=.TRUE. ; Elastic=5
else if (VariableSuffix.EQ.'.spc') then
  Decay= 600.0 ; Differ=.TRUE. ; Elastic=5
else
  print*, "  > @@@@@ ERROR: variable suffix not included: ", VariableSuffix
end if

DatabaseFile = "./../../../data/cruts/database/" // VariableSuffix(2:4) // &
		".??????????.dtb"
call GetBatch (DatabaseFile,Batch,Silent=1,ReturnUnalloc=1)
 
if (.not.associated(Batch)) then
  print*, "  > There are no prior accessions for this variable."
  DatabaseFile = "none"
else
  NBatch = size(Batch,1)
  DatabaseFile = Batch(NBatch)
  deallocate (Batch,stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### ERROR: Specify: Dealloc #####"
end if

if (ExtraTerm.EQ.1) call system ('printf "' // trim(VariableSuffix) // &
		'" >> ./../../../scratch//f90toidl.pipe')

if (ExtraTerm.EQ.1) then
 do
  print*, "  > Plot corrected stns ? (0=no,1=yes,2=dump, -1=help) "
  read (*,*,iostat=ReadStatus), QDumpView
  if (QDumpView.EQ.-1) then
    print*, "  > 1. allows interactive selection of plots, stn by stn"
    print*, "  > 2. dumps a set of plots to ./../../../scratch/"
  end if
  if (ReadStatus.LE.0.AND.QDumpView.GE.0.AND.QDumpView.LE.2) exit
 end do
else if (ExtraTerm.EQ.2) then
 QDumpView=2
else
 QDumpView=0
end if

if (QDumpView.GT.0) then
 do
  print*, "  > Enter the adjustment threshold, above which to dump stn. (-1=help)"
  read (*,*,iostat=ReadStatus), PlotThresh
  if (PlotThresh.EQ.-1) then
    print*, "  > The adj.thr. is RMSE of changes, in st.dev. of original."
    print*, "  > To dump all, set to zero; to plot most-adjusted, set >1."
  end if
  if (ReadStatus.LE.0.AND.PlotThresh.NE.-1) exit
 end do
end if

end subroutine SpecifyCommon

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

subroutine LoadDatabaseDummy

NDYear=1 ; NDStn=1
allocate (DInfo(NDStn,8), DData(NDYear,NMonth,NDStn), DYearAD(NDYear), &
	  DLocal(NDStn), DName(NDStn), DCty(NDStn), DCode(NDStn), &
	  DLat(NDStn), DLon(NDStn), DElv(NDStn), DNormals(NMonth,NDStn), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### LoadDatabaseDummy: alloc #####"
DData=DataMissVal ; DNormals=DataMissVal ; DYearAD=1990
DInfo=MissVal ; DCode=MissVal ; DLat=MissVal ; DLon=MissVal ; DElv=MissVal
DLocal="   nocode" ; DName="UNKNOWN" ; DCty="UNKNOWN"

end subroutine LoadDatabaseDummy

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

subroutine LoadDatabase

SubBeg=index(DatabaseFile,"/",.TRUE.)
FileDate=DatabaseFile((SubBeg+05):(SubBeg+10)) 
FileTime=DatabaseFile((SubBeg+11):(SubBeg+14))

call LoadCTS (DInfo,DLocal,DName,DCty,Data=DData,YearAD=DYearAD, &
		Lat=DLat,Lon=DLon,Elv=DElv,Code=DCode, &
		DtbNormals=DNormals,Silent=1,CallFile=DatabaseFile)
NDYear = size(DYearAD,1) ; NDStn = size(DData,3)
print "(a9,2(a2,a1),a2,a3,a2,a1,a2,a,i7,2(a,i4))", "   > Dtb ", &
		FileDate(5:6),".",FileDate(3:4),".",FileDate(1:2)," - ", &
		FileTime(1:2),":",FileTime(3:4),": ",NDStn," stns ", &
		DYearAD(1), "-", DYearAD(NDYear)

end subroutine LoadDatabase

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

subroutine LoadOriginal

call LoadCTS (OInfo,OLocal,OName,OCty,Data=OData,Code=OCode,OldCode=OOldCode,Silent=1, &
	      Lat=OLat,Lon=OLon,Elv=OElv,YearAD=YearAD,CallFile=DataFile, &
	      YearADMin=DYearAD(1),YearADMax=DYearAD(NDYear))
NYear=size(OData,1) ; NOStn=size(OData,3) ; OBeg=MissVal ; OEnd=MissVal

do XYear=1,NYear
  XMonth=0
  do
    XMonth=XMonth+1 ; XOStn=0
    do
      XOStn=XOStn+1
      if (OData(XYear,XMonth,XOStn).NE.DataMissVal) then
        if (OBeg.EQ.MissVal) OBeg=XYear
        OEnd=XYear
      end if
      if (XOStn.EQ.NOStn.OR.OEnd.EQ.XYear) exit
    end do
    if (XMonth.EQ.NMonth.OR.OEnd.EQ.XYear) exit
  end do
end do
NOYear=OEnd-OBeg+1

print "(a,11x,a2,i7,2(a,i4))", "   > New file ", ": ",NOStn, &
		" stns ",YearAD(OBeg), "-", YearAD(OEnd)

SubBeg=index(DataFile,".cts") 
DataSrcFile=DataFile ; DataSrcFile(SubBeg:(SubBeg+3))=".src"
call LoadCTS (TrashInfo,TrashLocal,TrashName,TrashCty, &
		Data=ODataSrc,YearAD=TrashYearAD,Silent=1,CallFile=DataSrcFile, &
		YearADMin=DYearAD(1),YearADMax=DYearAD(NDYear))
deallocate (TrashInfo,TrashLocal,TrashName,TrashCty,TrashYearAD, stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### LoadBoth: dealloc #####"

call CommonVecPer (YearAD,DYearAD,Beg,End,DBeg,DEnd)

end subroutine LoadOriginal

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

subroutine LoadParallel

ParallelFile=DataFile ; ParallelFile(QRetry:(QRetry+4))="homog"

call LoadCTS (TrashInfo,TrashLocal,TrashName,TrashCty,Code=PCode, &
		Data=PData,YearAD=PYearAD,Silent=1,CallFile=ParallelFile)
NPYear=size(PData,1) ; NPStn=size(PData,3)
print "(a,9x,a2,i7,2(a,i4))", "   > Homog file ", ": ",NPStn, &
		" stns ",PYearAD(1), "-", PYearAD(NPYear)

call CommonVecPer (YearAD,PYearAD,KBeg,KEnd,PBeg,PEnd)

if (PBeg.NE.MissVal) then	! common period between retry (O) and homog (P)
  XOStn=1 ; XPStn=1
  do				! search by stn
    if      (Code(XOStn) .EQ.MissVal) then
      XOStn=XOStn+1
    else if (PCode(XPStn).EQ.MissVal) then
      XPStn=XPStn+1
    else if (Code(XOStn).EQ.PCode(XPStn)) then		! same stn in O and P
      XYear=KBeg-1 ; ThisBeg => EarlBeg ; ThisEnd => EarlEnd
      do					! search by year
        XYear= XYear+1 ; XPYear= XYear-KBeg+PBeg 
	XMonth=0 ; Match=.FALSE. ; Clash=.FALSE.
	
	do					! search by month
	  XMonth=XMonth+1
	  					! year is present in O and P
	  if 	   ( Data( XYear,XMonth,XOStn).NE.DataMissVal.AND. &
	      	    PData(XPYear,XMonth,XPStn).NE.DataMissVal) then
	    Match=.TRUE.
	  else if (( Data( XYear,XMonth,XOStn).NE.DataMissVal.AND. &
	      	    PData(XPYear,XMonth,XPStn).EQ.DataMissVal).OR. &
		   ( Data( XYear,XMonth,XOStn).EQ.DataMissVal.AND. &
	      	    PData(XPYear,XMonth,XPStn).NE.DataMissVal)) then
	    Clash=.TRUE.
	  end if
	  
	  if (XMonth.EQ.NMonth.OR.Match.OR.Clash) exit
	end do
	
	if      (Match) then			! found match per
	  if      (ThisBeg(XOStn).EQ.MissVal) then	! unrecorded, so start
	    ThisBeg(XOStn)= XYear ; ThisEnd(XOStn)= XYear
	  else						! started
	    ThisEnd(XOStn)= XYear
	  end if
	else if (Clash) then			! found clash per
	  if      (ThisBeg(XOStn).EQ.MissVal) then	! mere continuation
	  	! nothing required
	  else						! indicates end of per
	    ThisBeg => LateBeg ; ThisEnd => LateEnd
	  end if
	end if
	
	if (XYear.EQ.KEnd) exit
      end do
      
      if (EarlBeg(XOStn).NE.MissVal.AND.LateBeg(XOStn).EQ.MissVal) then
        LateBeg(XOStn)=EarlBeg(XOStn) ; LateEnd(XOStn)=EarlEnd(XOStn)
      end if
      
      XOStn=XOStn+1 ; XPStn=XPStn+1
    else if (Code(XOStn).GT.PCode(XPStn)) then		! this P stn is not in O
      XPStn=XPStn+1
    else						! this O stn is not in P
      XOStn=XOStn+1
    end if
    
    if (XOStn.GT.NOStn.OR.XPStn.GT.NPStn) exit
  end do
end if

deallocate (TrashInfo,TrashLocal,TrashName,TrashCty,PCode,PData,PYearAD, stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### LoadParallel: dealloc #####"

end subroutine LoadParallel

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

subroutine GetCoverage

NLat=180 ; NLon=360 ; BoxLatDeg=1.0 ; BoxLonDeg=1.0

allocate (Got(NLat,NLon),Need(NLat,NLon),stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### GetCoverage: alloc #####"
Got=.FALSE. ; Need=.FALSE.

do XOStn=1,NOStn
  if (OLat(XOStn).NE.MissVal.AND.OLon(XOStn).NE.MissVal) then
    Enn=Enn+1
    XLat=floor(( 90.0+OLat(XOStn))/BoxLatDeg)+1 ; if (XLat.GT.NLat) XLat=NLat
    XLon=floor((180.0+OLon(XOStn))/BoxLonDeg)+1 ; if (XLon.GT.NLon) XLon=NLon
    Got(XLat,XLon)=.TRUE.
  end if
end do

call IdentifyRelevant (Got,Need,Decay)	! gridops.f90

NGot=count(Got) ; NNeed=count(Need)
print "(a,2i7)", "   > 1o cells: +stn, need: ",NGot,NNeed

end subroutine GetCoverage

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

subroutine Screen

do XDStn=1,NDStn
  if (DLat(XDStn).EQ.MissVal.OR.DLon(XDStn).EQ.MissVal) then
    QUseDStn = 0
  else
    XLat=floor(( 90.0+DLat(XDStn))/BoxLatDeg)+1 ; if (XLat.GT.NLat) XLat=NLat
    XLon=floor((180.0+DLon(XDStn))/BoxLonDeg)+1 ; if (XLon.GT.NLon) XLon=NLon
    
    if (Need(XLat,XLon)) then
      QUseDStn = 1
    else
      QUseDStn = 0
    end if
  end if
  
  if (QUseDStn.EQ.1) then
    if (QCountOnly.EQ.1) then
      NStn=NStn+1
    else
      XStn=XStn+1
      Local(XStn)=DLocal(XDStn) ; Name(XStn)=DName(XDStn) ; Cty(XStn)=DCty(XDStn)
      Lat(XStn)=DLat(XDStn) ; Lon(XStn)=DLon(XDStn) ; Elv(XStn)=DElv(XDStn)
  
      do XDYear=DBeg,DEnd
        XYear=Beg+(XDYear-DBeg)			
        do XMonth=1,NMonth
          Data(XYear,XMonth,XStn) = DData(XDYear,XMonth,XDStn)
        end do
      end do
    end if
  end if
end do

if (QCountOnly.EQ.0) then
  print "(a,2x,a2,i7,a)", "   > Restrict database ", ": ",(NStn-NOStn)," stns "
  deallocate (DInfo,DData,DLocal,DName,DCty,DCode,DLat,DLon,DElv, &
  	      Got,Need,stat=AllocStat)
  if (AllocStat.NE.0) print*, "  > ##### Screen: dealloc #####"
end if

end subroutine Screen

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

subroutine SpecComb

allocate (Data(NYear,NMonth,NStn), DataSrc(NYear,NMonth,NStn), &
	  Local(NStn), Name(NStn), Cty(NStn), Code(NStn), &
	  Lat(NStn), Lon(NStn), Elv(NStn), OldCode(NStn), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### SpecComb: alloc #####"

Data=DataMissVal ; DataSrc=DataMissVal
Local="   nocode" ; Name="UNKNOWN" ; Cty="UNKNOWN"
Code=MissVal ; OldCode=MissVal ; Lat=MissVal ; Lon=MissVal ; Elv=MissVal

do XOStn=1,NOStn
    Code(XOStn)=OCode(XOStn) ; OldCode(XOStn)=OOldCode(XOStn) ; Lat(XOStn)=OLat(XOStn)
    Lon(XOStn)=OLon(XOStn) ; Elv(XOStn)=OElv(XOStn)
    Local(XOStn)=OLocal(XOStn) ; Name(XOstn)=OName(XOStn) ; Cty(XOStn)=OCty(XOStn)
    do XYear=1,NYear
      do XMonth=1,NMonth
        Data   (XYear,XMonth,XOStn)=OData   (XYear,XMonth,XOStn)
        DataSrc(XYear,XMonth,XOStn)=ODataSrc(XYear,XMonth,XOStn)
      end do
    end do
end do

deallocate (OInfo,OLocal,OName,OCty,OCode,OOldCode,OLat,OLon,OElv,ODataSrc, &
		stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### SpecComb: dealloc 1 #####"

end subroutine SpecComb

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

subroutine MakeArrays

allocate (Disc(NYear,NStn),DiscCrude(NYear,NStn),Trust(NYear,NStn), &
	  Believe(NYear,NStn),RefTS(NYear,NMonth,NStn),Examine(NStn), &
	  Sought(NStn),GotRef(NStn),StnLen(NStn), &
	  EarlBeg(NStn),EarlEnd(NStn),LateBeg(NStn),LateEnd(NStn),stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### MakeArrays: alloc #####"
Disc=.FALSE. ; DiscCrude=.FALSE. ; Trust=.TRUE. ; Believe=.FALSE.
Verbose=.TRUE. ; PlotAllManip=.FALSE. ; RefTS=DataMissVal
EarlBeg=MissVal ; EarlEnd=MissVal ; LateBeg=MissVal ; LateEnd=MissVal

Examine=.FALSE.
do XStn=1,NOStn
    Examine(XStn)=.TRUE.
    
    BegO=0 ; EndO=0
    do XYear=1,NYear
      do XMonth=1,NMonth
        if (Data(XYear,XMonth,XStn).NE.DataMissVal) then
	  if (BegO.EQ.0) BegO=XYear
	  EndO=XYear
	end if
      end do
    end do
    StnLen(XStn)=EndO-BegO+1
end do
Sought=Examine

end subroutine MakeArrays

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

subroutine SaveTwo

allocate (AdjSrc(NYear,NMonth,NStn), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### SaveTwo: alloc: AdjSrc #####"
AdjSrc=DataMissVal ; LogAdj=0 ; LogNon=0

do XYear=1,NYear
  do XMonth=1,NMonth
    do XStn=1,NStn
      if (Examine(XStn)) then
        if (Adj(Xyear,XMonth,XStn).NE.DataMissVal) then
      	  AdjSrc(Xyear,XMonth,XStn) = DataSrc(Xyear,XMonth,XStn)
      	  LogAdj=LogAdj+1
        else if (Data(Xyear,XMonth,XStn).NE.DataMissVal) then
          LogNon=LogNon+1
        end if
      end if
    end do
  end do
end do 
print "(a,2i7)", "   > Data to homog, retry: ",LogAdj,LogNon
write (99,"(a,2i7)"), "   > Data to homog, retry: ",LogAdj,LogNon

call MakeStnInfo (Info,Code,OldCode,Lat,Lon,Elv,1, &
		  YearAD=YearAD,Data=Adj,Silent=1,QBlank=QBlank)
if (QBlank) then
  print*, "  > It has not been possible to check any data."
else
  print "(2a)", "   > Save file: ", trim(SaveFileTwo)
  SubBeg=index(SaveFileTwo,".cts")  ; SaveSrcFile=SaveFileTwo(1:(SubBeg-1)) // ".src"
  call SaveCTS (Info,Local,Name,Cty,Data=Adj,YearAD=YearAD, &
		CallFile=SaveFileTwo,Silent=1)
  call SaveCTS (Info,Local,Name,Cty,Data=AdjSrc,YearAD=YearAD, &
		CallFile=SaveSrcFile,Silent=1)
end if

call DumpAdjHdr
call DumpAdjPer

deallocate (Info, stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### SaveTwo: dealloc: Info #####"

do XStn=1,NStn
  if (.NOT.Examine(XStn)) Code(XStn)=MissVal	! remove dtb stns from retry
  
  do XYear=1,NYear
    do XMonth=1,NMonth
      if (Data(Xyear,XMonth,XStn).EQ.DataMissVal) &
      	  DataSrc(Xyear,XMonth,XStn) = DataMissVal
    end do
  end do
end do 

call MakeStnInfo (Info,Code,OldCode,Lat,Lon,Elv,1, &
		  YearAD=YearAD,Data=Data,Silent=1,QBlank=QBlank)
if (QBlank) then
	! nothing here
else
  SubBeg=index(SaveFileTwo,"homog") ; SaveFileTwo(SubBeg:(SubBeg+4))="retry"
  SubBeg=index(SaveFileTwo,".cts")  ; SaveSrcFile=SaveFileTwo(1:(SubBeg-1)) // ".src"
  call SaveCTS (Info,Local,Name,Cty,Data=Data,YearAD=YearAD, &
		CallFile=SaveFileTwo,Silent=1)
  call SaveCTS (Info,Local,Name,Cty,Data=DataSrc,YearAD=YearAD, &
		CallFile=SaveSrcFile,Silent=1)
end if

deallocate (AdjSrc,DataSrc,Info, stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### SaveTwo: dealloc: *Src #####"

end subroutine SaveTwo

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

subroutine DumpAdjHdr

SubBeg=index(SaveFileTwo,".cts") ; HdrFile=SaveFileTwo(1:(SubBeg-1)) // ".adj.hdr"

call QuickSort (Reals=AdjStn,Order=Order,NMiss=NMiss)

CallForm="(f7.2,13x)"
do XStn=1,NStn
    String20 = GetTextFromReal (AdjStn(XStn),CallForm=CallForm)
    Local(XStn) = adjustr(String20(1:9))
end do

call SaveCTS (Info,Local,Name,Cty,CallFile=HdrFile,HeadOnly=1,Silent=1,Order=Order)
		    
deallocate (Order, stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### DumpAdjHdr: dealloc #####"

end subroutine DumpAdjHdr

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

subroutine DumpAdjPer

SubBeg=index(SaveFileTwo,".cts") ; PerFile=SaveFileTwo(1:(SubBeg-1)) // ".adj.per"

allocate (AdjSea(NYear,4),AdjAnn(NYear), stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### DumpAdjPer: alloc #####"

call FillSeaAnnMean (YearAD,AdjMon,AdjSea,AdjAnn)
call SavePER (PerFile,YearAD,0,Monthly=AdjMon,Seasonal=AdjSea,Annual=AdjAnn,NoResponse=1)

deallocate (AdjSea,AdjAnn, stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### DumpAdjPer: dealloc #####"

end subroutine DumpAdjPer

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

subroutine PlotDiscStn

XIterate=1

do XStn = 1, NStn
  if (Examine(XStn).AND.AdjStn(XStn).GE.PlotThresh) then
    XYear=0 ; QAbs=0 ; QAnom=0 ; QStep=0 ; QDump=99
    do
     XYear=XYear+1
     
     if (Disc(XYear,XStn).OR.PlotAllManip) then
      call CalcClimatology
      QDump=7 ; call DumpForIDL ; QStep=1
      QDump=8 ; call DumpForIDL ; QDump=9 ; call DumpForIDL
      
      do
        do
          print "(5a)", "   > Plot ", trim(Name(XStn)), " (", trim(Cty(XStn)), &
          		") (0=exit,99=help)"
          read (*,*,iostat=ReadStatus), QDump
          if (ReadStatus.LE.0) exit
        end do
        
        if (QDump.GE.1.AND.QDump.LE.9) then
          call DumpForIDL

          if      (QDump.LT.4) then
            QAbs=1
          else if (QDump.LT.7) then
            QAnom=1
          else
            QStep=1
          end if
        else if (QDump.EQ.99) then
          print*, "  > ABS:  1=orig,2=refTS,3=okay"
          print*, "  > ANOM: 4=orig,5=refTS,6=okay"
          print*, "  > DIFF: 7=1-2, 8=1-3,  9=3-2"
        end if
        
        if (QDump.EQ.0) exit
      end do
     end if
     
     if (XYear.EQ.NYear.OR.QDump.EQ.0) exit
    end do
  end if 
end do

end subroutine PlotDiscStn

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

subroutine DumpDiscStn

XIterate=1 ; write (99,*)
write (99,"(a)"), "   PLOT      STAT"

do XStn = 1, NStn
  if (Examine(XStn).AND.AdjStn(XStn).GT.PlotThresh) then
    QAbs=0 ; QAnom=0 ; QStep=0 ; QDump=99
    write (99,"(i7,f10.2)"), Code(XStn), AdjStn(XStn)
    call CalcClimatology
      
    do QDump = 1, 9
          call DumpForIDL

          if      (QDump.LT.4) then
            QAbs=1
          else if (QDump.LT.7) then
            QAnom=1
          else
            QStep=1
          end if
          
	  if (ExtraTerm.EQ.1) then
            SubBeg = index(DumpFile,".txt")
            DumpFile = DumpFile(1:SubBeg) // "eps"
            do
              inquire (file=DumpFile, exist=Plotted)
              if (Plotted) exit
            end do
	  end if
    end do
  end if 
end do

end subroutine DumpDiscStn

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

subroutine CalcClimatology

Climatology=0
do XMonth = 1, NMonth
  OpTot=0 ; OpEn=0
  do XYear = 1, NYear
    if (RefTS(XYear,XMonth,XStn).NE.DataMissVal) then
      OpEn=OpEn+1 ; OpTot=OpTot+real(RefTS(XYear,XMonth,XStn))
    end if
  end do
  if (OpEn.Gt.0) then
    Climatology(XMonth)=nint(OpTot/OpEn)
    if ((.NOT.Differ).AND.OpTot.EQ.0.0) Climatology(XMonth)=0.1
  end if
end do

end subroutine CalcClimatology

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

subroutine DumpForIDL

DumpText(5:8) = "Orig"

if      (QDump.EQ.1) then
	FileText = "a.oriabs" ; DumpText(1:4) = "Abso" ; DumpTarget => OData
	Title = "Original" ; if (QAbs.EQ.1) DumpText(5:8) = "Revi"
else if (QDump.EQ.2) then
	FileText = "b.refabs" ; DumpText(1:4) = "Abso" ; DumpTarget => RefTS
	Title = "Reference" ; if (QAbs.EQ.1) DumpText(5:8) = "Revi"
else if (QDump.EQ.3) then
	FileText = "c.yesabs" ; DumpText(1:4) = "Abso" ; DumpTarget => Adj
	Title = "Revised" ; if (QAbs.EQ.1) DumpText(5:8) = "Revi"
else if (QDump.EQ.4) then
	FileText = "d.oriano" ; DumpText(1:4) = "Anom" ; DumpTarget => OData
	if (Differ) then
	  Title = "Original (anomalies)" 
	else
	  Title = "Original : normal (ratio)" 
	end if
	if (QAnom.EQ.1) DumpText(5:8) = "Revi"
else if (QDump.EQ.5) then
	FileText = "e.refano" ; DumpText(1:4) = "Anom" ; DumpTarget => RefTS
	if (Differ) then
	  Title = "Reference (anomalies)" 
	else
	  Title = "Reference : normal (ratio)"
	end if
	if (QAnom.EQ.1) DumpText(5:8) = "Revi"
else if (QDump.EQ.6) then
	FileText = "f.yesano" ; DumpText(1:4) = "Anom" ; DumpTarget => Adj
	if (Differ) then
	  Title = "Revised (anomalies)" 
	else
	  Title = "Revised : normal (ratio)"
	end if
	if (QAnom.EQ.1) DumpText(5:8) = "Revi"
else if (QDump.EQ.7) then
	FileText = "g.shifts" ; DumpText(1:4) = "Step" ; DumpTarget => OData
	if (Differ) then
	  Title = "Original minus Reference"
	else
	  Title = "Original : Reference (ratio)"
	end if
	if (QStep.EQ.1) DumpText(5:8) = "Revi"
else if (QDump.EQ.8) then
	FileText = "h.change" ; DumpText(1:4) = "Step" ; DumpTarget => OData
	if (Differ) then
	  Title = "Original minus Revised" 
	else
	  Title = "Original : Revised (ratio)" 
	end if
	if (QStep.EQ.1) DumpText(5:8) = "Revi"
else if (QDump.EQ.9) then
	FileText = "i.cleand" ; DumpText(1:4) = "Step" ; DumpTarget => RefTS
	if (Differ) then
	  Title = "Revised minus Reference" 
	else
	  Title = "Revised : Reference (ratio)" 
	end if
	if (QStep.EQ.1) DumpText(5:8) = "Revi"
end if

StnText  = GetTextFromInt(Code(XStn))
IterText = GetTextFromInt(XIterate)
DumpFile = './../../../scratch/' // trim(adjustl(StnText)) // '.' // FileText // '.txt'

open (80,file=DumpFile,status="replace",action="write")
write (80,"(i8,x,a20,x,a13,x,i4,x,a8,x,i2)"), Code(XStn),Name(XStn), &
			Cty(XStn),NYear,DumpText,QDumpView
write (80,"(a80)"), Title
do XYear = 1,NYear
    DumpData=DataMissVal
    
    if (Differ) then
      call GrabMeans
    else
      call GrabTotals
    end if
    
    do XMonth=1,NMonth
      if (DumpData(XMonth).GT.99999.OR.DumpData(XMonth).LT.-9999) &
      		 DumpData(XMonth) = DataMissVal
    end do
    
    write (80,"(i4,12i5,f10.2)"), YearAD(XYear), &
    	(DumpData(XMonth), XMonth=1,NMonth), OpMean
end do
close (80)
  
if (ExtraTerm.EQ.1) call system &
	('printf "' // trim(DumpFile) // '" >> ./../../../scratch/f90toidl.pipe')

end subroutine DumpForIDL

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

subroutine GrabMeans

OpTot=0 ; OpEn=0 ; OpMean=MissVal ; OpValid=0			

do XMonth=1,NMonth
      if (DumpTarget(XYear,XMonth,XStn).NE.DataMissVal) then
      	if      (QDump.LT.4) then
	  DumpData(XMonth) = DumpTarget(XYear,XMonth,XStn)
        else if (QDump.LT.7) then
	  DumpData(XMonth) = DumpTarget(XYear,XMonth,XStn)-Climatology(XMonth)
	else if (QDump.EQ.7) then
          if (RefTS(XYear,XMonth,XStn).NE.DataMissVal) &
              DumpData(XMonth) = OData(XYear,XMonth,XStn)-RefTS(XYear,XMonth,XStn)
        else if (QDump.EQ.8) then
          if (Adj(XYear,XMonth,XStn).NE.DataMissVal) &
              DumpData(XMonth) = OData(XYear,XMonth,XStn)-Adj(XYear,XMonth,XStn)
	else if (QDump.EQ.9) then
          if (Adj(XYear,XMonth,XStn).NE.DataMissVal) &
              DumpData(XMonth) = Adj(XYear,XMonth,XStn)-RefTS(XYear,XMonth,XStn)
	end if
      end if
      
      if (DumpData(XMonth).NE.DataMissVal) then		! month = valid
        OpTot=OpTot+DumpData(XMonth) ; OpEn=OpEn+1 ; OpValid=OpValid+1
      else if (QDump.LT.7) then				! est month from yr-5, yr-1
        OpAdd=0 ; OpWin=0
        do XWindow=XYear-5,XYear-1
          if (XWindow.GT.0.AND.XWindow.LE.NYear) then
            if (DumpTarget(XWindow,XMonth,XStn).NE.DataMissVal) then
              OpAdd=OpAdd+DumpTarget(XWindow,XMonth,XStn) ; OpWin=OpWin+1
            end if
          end if
        end do
        if (OpWin.GT.1) then
          if (QDump.LT.4) then
            OpTot=OpTot+(OpAdd/OpWin) ; OpEn=OpEn+1
          else
            OpTot=OpTot+((OpAdd/OpWin)-Climatology(XMonth)) 
	    OpEn=OpEn+1
          end if
        end if
      else						! est month from mon-2,mon+2
        OpAdd=0 ; OpWin=0 ; XWindow=XMonth-3
        do
          XWindow=XWindow+1
          if (Xwindow.GT.0.AND.Xwindow.LE.NMonth) then
            if (DumpData(XWindow).NE.DataMissVal) then
              OpAdd=OpAdd+DumpData(XWindow) ; OpWin=OpWin+1
            end if
          end if
          if (XWindow.EQ.(XMonth+2).OR.XWindow.EQ.12) exit
        end do
        if (OpWin.GT.0) then
            OpTot=OpTot+(OpAdd/OpWin) ; OpEn=OpEn+1
        end if
      end if
end do
    
if (OpValid.GT.6) OpMean=OpTot/opEn
    
end subroutine GrabMeans

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

subroutine GrabTotals

OpTot=0 ; OpEn=0 ; OpMean=MissVal ; OpValid=0 ; OpClim=0

do XMonth=1,NMonth
        RealTarget = real(DumpTarget(XYear,XMonth,XStn))
        RealClim   = real(Climatology(XMonth))
        RealOData  = real(OData(XYear,XMonth,XStn))
        RealRefTS  = real(RefTS(XYear,XMonth,XStn))
        RealAdj    = real(Adj(XYear,XMonth,XStn))
        
      	if      (QDump.LT.4) then			! fill monthly data array
      	  if (RealTarget.NE.DataMissVal) then
	    DumpData(XMonth) = DumpTarget(XYear,XMonth,XStn)
	    OpTot=OpTot+RealTarget 
	    OpValid=OpValid+1
	  else
	    OpTot=OpTot+RealClim
	  end if
        else if (QDump.LT.7) then
	  if (RealTarget.NE.DataMissVal) then
	    DumpData(XMonth) = nint(100.0*RealTarget/RealClim)
	    OpTot=OpTot+RealTarget 
	    OpValid=OpValid+1
	  else
	    OpTot=OpTot+RealClim
	  end if
	else if (QDump.EQ.7) then
          if (RealOData.NE.DataMissVal.AND.RealRefTS.NE.DataMissVal.AND. &
	  		RealRefTS.NE.0) then
	    DumpData(XMonth) = nint(100.0*RealOData/RealRefTS)
	    OpTot=OpTot+((RealOData/RealRefTS)*RealClim)
	    OpValid=OpValid+1
	  else
	    OpTot=OpTot+RealClim
	  end if
        else if (QDump.EQ.8) then
          if (RealOData.NE.DataMissVal.AND.RealAdj.NE.DataMissVal.AND. &
	  		RealAdj.NE.0) then
	    DumpData(XMonth) = nint(100.0*RealOData/RealAdj)
	    OpTot=OpTot+((RealOData/RealAdj)*RealClim)
	    OpValid=OpValid+1
	  else
	    OpTot=OpTot+RealClim
	  end if
	else if (QDump.EQ.9) then
          if (RealRefTS.NE.DataMissVal.AND.RealAdj.NE.DataMissVal.AND. &
	  		RealRefTS.NE.0) then
	    DumpData(XMonth) = nint(100.0*RealAdj/RealRefTS)
	    OpTot=OpTot+((RealAdj/RealRefTS)*RealClim)
	    OpValid=OpValid+1
	  else
	    OpTot=OpTot+RealClim
	  end if
	end if
	
	OpClim=OpClim+RealClim
end do
    
if (OpValid.GT.6) then
      if      (QDump.LT.4) then
        OpMean=OpTot
      else
        OpMean=nint(100.0*OpTot/OpClim)
      end if
end if
    
end subroutine GrabTotals

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

end program Homogiter
