! opcruts.f90 ! f90 program written by Tim Mitchell on 11.02.02 ! last modified on 01.05.02 ! program to manipulate CRU ts files (.cts .hdr) ! pgf90 -Mstandard -Minfo -fast -Mscalarsse -Mvect=sse -Mflushz ! -o ./../cruts/opcruts filenames.f90 time.f90 grimfiles.f90 ! crutsfiles.f90 saveperfiles.f90 annfiles.f90 cetgeneral.f90 basicfun.f90 ! wmokey.f90 gridops.f90 grid.f90 ctyfiles.f90 ! ./../cruts/opcruts.f90 2> /tyn1/tim/scratch/stderr.txt program OpCRUts use FileNames use Time use GrimFiles use CRUtsFiles use SavePerFiles use AnnFiles use CETGeneral use BasicFun use WMOKey use GridOps use Grid use CtyFiles implicit none real, pointer, dimension (:,:,:) :: Stdev,Means,RealData real, pointer, dimension (:,:) :: StnMon,StnSea,SumsPer,NormMean,NormStdev real, pointer, dimension (:,:) :: RefGridLat,RefGridLon real, pointer, dimension (:) :: SrcEn,SrcTot,SrcTotSq real, pointer, dimension (:) :: StnAnn, Scatter, SumsAnn real, pointer, dimension (:) :: ALat,ALon,AElv,BLat,BLon,BElv,CLat,CLon,CElv real, dimension (12) :: ThreshLo,ThreshHi,MonthMeans,TheoryMax real, dimension ( 4) :: RefBounds integer, pointer, dimension (:,:,:) :: Data,DataA,DataB,DataC integer, pointer, dimension (:,:,:) :: DataSrc,DataASrc,DataBSrc,DataCSrc integer, pointer, dimension (:,:,:) :: LogMeans,LogStdev integer, pointer, dimension (:,:) :: DtbNormalsA,DtbNormalsC integer, pointer, dimension (:,:) :: HulmeA,Normals,RefGrid,MonthLengths integer, pointer, dimension (:,:) :: StnInfoA,StnInfoB,StnInfoC integer, pointer, dimension (:,:) :: LogPass,LogMiss,LogSkip,LogFail,LogAny,LogNorm integer, pointer, dimension (:) :: YearAD,StnYearAD,AYearAD,BYearAD,CYearAD,Order integer, pointer, dimension (:) :: CtyCode0,CtyCode1,CtyReg integer, pointer, dimension (:) :: AStn,BStn,CStn, AStnOld,BStnOld,CStnOld, MapCA,MapCB integer, pointer, dimension (:) :: StnSrcCodeA,StnSrcDateA integer, pointer, dimension (:) :: NmlYr0,NmlYr1,NmlSrc,NmlInc character (len=80), pointer, dimension (:) :: SaveBatch,DatabaseBatch character (len=80), pointer, dimension (:) :: Bat01,Bat02,Bat03,Bat04,Bat05,Bat06 character (len=80), pointer, dimension (:) :: Bat07,Bat08,Bat09,Bat10,Bat11,Bat12 character (len=20), pointer, dimension (:) :: StnNameA,StnNameB,StnNameC,AUni,Source character (len=13), pointer, dimension (:) :: StnCtyA,StnCtyB,StnCtyC,CtyName,CtyFinal character (len=09), pointer, dimension (:) :: StnLocalA,StnLocalB,StnLocalC,ColTitles character (len=04), pointer, dimension (:) :: StnSrcSuffixA character (len=20), dimension (9) :: VersionKey=(/"WMO STATIONS MAY 98","WMO MAY 2002","NCDC MAY 2002", & "GHCN V2 TMP SERIES","HULME PRECIP","LISTER MAY 02", & "CRU NORMALS","CRU BIG.HDR.HYP","CRU TMP SERIES"/) character (len=04), dimension (4) :: LogName=(/"PASS","MISS","SKIP","FAIL"/) character (len=09), dimension(12) :: RegTitles=(/' Globe',' Europe',' ex-USSR', & ' Mid-East',' Asia',' Africa', & ' NAmerica',' CAmerica',' SAmerica', & ' Antarc',' Oceania',' Marine'/) character (len=02), dimension (12) :: MonthTxt=(/"01","02","03","04","05","06","07","08","09","10","11","12"/) real, dimension(12), parameter :: Ephemeris=(/-0.346,-0.216,-0.029, 0.173, 0.331, 0.403, & 0.369, 0.237, 0.044,-0.158,-0.316,-0.387/) real, parameter :: MissVal = -999.0 integer, parameter :: DataMissVal = -9999 integer, parameter :: MultiSource=-888 character (len=80) :: LogMeansFile="/cru/mikeh1/f709762/scratch/log/log-opcruts-means.cts" character (len=80) :: LogStdevFile="/cru/mikeh1/f709762/scratch/log/log-opcruts-stdev.cts" logical :: ValidNorm real :: Lat0,Lat1,Lon0,Lon1,Elv0,Elv1, PrecLat,PrecLon,PrecElv real :: DataMulti,ThreshStdev,ThreshReject,ThreshPercent,ThreshOpCalc real :: EntryReal,Limit, PrevLat,PrevLon, Constant, SeqStatus, Sigma,Middl,Excess real :: MissThresh,StdevThresh,DistanceThresh,Factor, ExeSpace,WyeSpace real :: OpVal,OpTot,OpEn,OpTotSq,OpStdev,OpMean,OpDiff,OpMean0,OpMean1,OpStdev0,OpStdev1,OpStdevJ real :: Distance,DecayDistance,Loaded,LatRad,Denom,Numer integer :: ReadStatus,AllocStat integer :: QMenu,QDataHeadLoad,QDataHeadSave,QTrueQuasi,QLongType,QCrossDL,QFile,QNoStdev,QNoPer integer :: QDiff,QFake,QAlter,QManual,QReverse,QShift,QType,QSource,QOperation,QRestrict,QCombine integer :: QManCheck,QReject,QNRMfile,QOutput,QSignCheck,QMisMatch,QStoreOld,QHomogSource,QMerge integer :: QAnomPercent,QPosOnly integer :: NAStn,NBStn,NCStn,NInfo,NStnYear,NAYear,NBYear,NCYear,NMonth,NVersion,NCty,NReg,NSrc integer :: XAStn,XBStn,XCStn,XInfo,XStnYear,XAYear,XBYear,XCYear,XMonth,XVersion,XCty,XReg,XSrc integer :: NBatch,NExe,NWye,NFile integer :: XBatch,XExe,XWye,XFile integer :: XAYear0,XLog,XSeason,XSeasonMonth,XSeasonYear,XMonth0,XYear0,XMonth1,XYear1,XBMonth integer :: AddYearAD0,AddYearAD1,PrevStn,EquiStn,RegSub0,StatType,SourceCode,SuffixBeg, Digits integer :: YearAD0,YearAD1,Month0,Month1, AStart,AEnd,BStart,BEnd,CAStart,CAEnd,CBStart,CBEnd integer :: IntLat,IntLon,IntElv, LatMV,LonMV,ElvMV,DataMV, LatF,LonF,ElvF integer :: FakeStn,OrigStn,NewStn, TotA,TotB,TotAB, Min,Max,MinImpose,MaxImpose integer :: Log01,Log02,Log03,Log04,Log05,Log06,Log07,Log08,Log09,Log11,Log12,Log13 integer :: Log0,Log1,Log2,Log3,Log4,Log5,Log6,Log7 integer :: InRange, CheckYear0,CheckYear1,SaveYearAD0,SaveYearAD1, NormMin,StrLen,SubBeg integer :: RefBoxes,SrcRemove character (len=80) :: GivenFile,LoadFileA,LoadFileB,LoadFileC,SaveFileA,SaveFileB,SaveFileC,HeadFormat character (len=80) :: LoadFileASrc,LoadFileBSrc,SaveFileASrc,SaveFileBSrc,SaveFileCSrc,Stem,Tip character (len=80) :: CurrStr,PrevStr,Variable,Title,Trash character (len=80) :: DatabaseFilter,DatabaseFilterSrc,DatabaseFileL,DatabaseSrcFileL character (len=20) :: SourceStr,EntryString,YearTxt,LineFormat character (len=08) :: Date character (len=04) :: LoadSuffix,SaveSuffix,SaveFileType,FileSuffix,TimeVal call Intro call Menu if (QMenu.EQ. 1) call ConvertToHead if (QMenu.EQ. 2) call ConvertToPerSet if (QMenu.EQ. 3) call GenerateSrcFile if (QMenu.EQ. 4) call ConvertNewCode if (QMenu.EQ. 5) call AddSourceHdr if (QMenu.EQ. 6) call ConvertWMO if (QMenu.EQ. 7) call ConvertLegacy if (QMenu.EQ.10) call CorrectError if (QMenu.EQ.11) call IDaddAB if (QMenu.EQ.12) call CombineAB if (QMenu.EQ.13) call DescribeAPer if (QMenu.EQ.14) call DescribeAAnn if (QMenu.EQ.18) call OperateAk if (QMenu.EQ.19) call OperateAB if (QMenu.EQ.21) call GetLatLongRect if (QMenu.EQ.22) call TruncateDate if (QMenu.EQ.23) call QCImplicitStdev if (QMenu.EQ.25) call Anomalise if (QMenu.EQ.26) call FindClosest if (QMenu.EQ.27) call MultiplyCodes if (QMenu.EQ.28) call SyncCtsSrc if (QMenu.EQ.29) call ImpossibleElev if (QMenu.EQ.30) call ConvertDegHun if (QMenu.EQ.31) call MultiplyNRM if (QMenu.EQ.34) call PruneSource if (QMenu.EQ.40) call ConvertVariableDtb if (QMenu.EQ.41) call ConvertVariableCts call Finish contains !******************************************************************************* subroutine Intro open (99,file="./../../../scratch/log-opcruts.dat",status="replace",action="write") print* print*, " > ***** OpCRUts: manipulates .cts .hdr .src .dtb .dts files *****" print* NMonth = 12 ; NVersion = 9 ; NSrc = 1000 end subroutine Intro !******************************************************************************* subroutine Menu print*, " > Select an operation to perform (0=list): " do read (*,*,iostat=ReadStatus), QMenu if (QMenu.EQ.0) then print*, " > 1. Convert into a CRU ts file." print*, " > 2. Convert into a set of .per files." print*, " > 3. Generate a parallel .src file." print*, " > 4. Convert from Mark New source code file" print*, " > 5. Add source info to .hdr file" print*, " > 6. Convert WMO data file to .hdr file" print*, " > 7. Convert legacy .cts to .cts file" print*, " > 11. Identify additionality of B over A." print*, " > 12. Combine A (priority) and B." print*, " > 13. Describe A by month (output .per file)." print*, " > 14. Describe A by continent (output .ann file)." print*, " > 18. Operate A.k" print*, " > 19. Operate A.B" print*, " > 21. Extract all data within lat/long rectangle." print*, " > 22. Truncate by date." print*, " > 23. Quality control using implicit stdev." print*, " > 25. Anomalise .cts (now anomdtb.f90)" print*, " > 26. Find closest stns" print*, " > 27. Multiply station codes." print*, " > 28. Check .cts and .src are in sync" print*, " > 29. Remove impossible elevations." print*, " > 30. Convert deg+minutes to deg+hundredths" print*, " > 31. Multiply .nrm" print*, " > 34. Remove data from a selected source" print*, " > 40. Convert variable .dtb" print*, " > 41. Convert variable .cts" end if if (ReadStatus.LE.0.AND.QMenu.GE.1) exit end do end subroutine Menu !******************************************************************************* subroutine ConvertToHead print*, " > Load a true (=1), quasi (=2), MikeH (=3), PhilJ (=4) file?" do read (*,*,iostat=ReadStatus), QTrueQuasi if (ReadStatus.LE.0.AND.QTrueQuasi.GE.1.AND.QTrueQuasi.LE.4) exit end do if (QTrueQuasi.EQ.1) then print*, " > Load a .src (=0) .cts (=1) .hdr (=2) .dtb (=3) .dts (=4) file ?" do read (*,*,iostat=ReadStatus), QDataHeadLoad if (ReadStatus.LE.0.AND.QDataHeadLoad.GE.0.AND.QDataHeadLoad.LE.4) exit end do else if (QTrueQuasi.EQ.2) then print*, " > Load a data (=1) or header (=2) file ?" do read (*,*,iostat=ReadStatus), QDataHeadLoad if (ReadStatus.LE.0.AND.QDataHeadLoad.GE.1.AND.QDataHeadLoad.LE.2) exit end do else QDataHeadLoad = 1 end if if (QTrueQuasi.EQ.1) then if (QDataHeadLoad.EQ.0) LoadSuffix = ".src" if (QDataHeadLoad.EQ.1) LoadSuffix = ".cts" if (QDataHeadLoad.EQ.2) LoadSuffix = ".hdr" if (QDataHeadLoad.EQ.3) LoadSuffix = ".dtb" if (QDataHeadLoad.EQ.4) LoadSuffix = ".dts" else if (QTrueQuasi.EQ.4) then LoadSuffix = " " HeadFormat = "(i6,i4,i5,i5,x,a20,x,a13,x,4i4)" QLongType = 2 LatF=10 ; LonF=10 ; ElvF=1 ; DataMV=-999 LatMV=-999 ; LonMV=-1999 ; ElvMV=-999 else LoadSuffix = " " if (QTrueQuasi.EQ.2) then print*, " > Enter the header line format (i?,i?,i?,i?,a??,a??,i?,i?,i?,a?): " do read (*,*,iostat=ReadStatus), HeadFormat if (ReadStatus.LE.0.AND.HeadFormat.NE."") exit end do print*, " > Are the longs 0:180:-180:0 (=1), 0:-180:180:0 (=2), 0:360 (=3): " do read (*,*,iostat=ReadStatus), QLongType if (ReadStatus.LE.0.AND.QLongType.GE.1.AND.QLongType.LE.3) exit end do print*, " > Enter the lat,lon,elv factors (integers):" do read (*,*,iostat=ReadStatus), LatF,LonF,ElvF if (ReadStatus.LE.0) exit end do print*, " > Enter the lat,lon,elv missing values (integers):" do read (*,*,iostat=ReadStatus), LatMV,LonMV,ElvMV if (ReadStatus.LE.0) exit end do if (QDataHeadLoad.EQ.1) then print*, " > Enter the data missing value in the file: " do read (*,*,iostat=ReadStatus), DataMV if (ReadStatus.LE.0) exit end do end if end if end if print*, " > Select the file to load, with suffix: ", LoadSuffix do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,LoadSuffix) print*, " > Save as .src (=0) .cts (=1) .hdr (=2) .dtb (=3) .dts (=4) file ?" do read (*,*,iostat=ReadStatus), QDataHeadSave if (ReadStatus.LE.0.AND.QDataHeadSave.GE.0.AND.QDataHeadSave.LE.4) exit end do if (QDataHeadSave.EQ.0) then SaveSuffix = ".src" ; QDataHeadSave = 1 else if (QDataHeadSave.EQ.1) then SaveSuffix = ".cts" else if (QDataHeadSave.EQ.2) then SaveSuffix = ".hdr" else if (QDataHeadSave.EQ.3) then SaveSuffix = ".dtb" else if (QDataHeadSave.EQ.4) then SaveSuffix = ".dts" end if print*, " > Select the file to save, with suffix: ", SaveSuffix do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileA = SavePath (GivenFile,SaveSuffix) print*, " > Loading..." if (QTrueQuasi.EQ.1) then if (QDataHeadLoad.EQ.0.OR.QDataHeadLoad.EQ.1) then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=YearAD,CallFile=LoadFileA) else if (QDataHeadLoad.EQ.2) then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & CallFile=LoadFileA,HeadOnly=1) else if (QDataHeadLoad.EQ.3.OR.QDataHeadLoad.EQ.4) then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,DtbNormals=DtbNormalsA,YearAD=YearAD,CallFile=LoadFileA) end if else if (QTrueQuasi.EQ.2) then if (QDataHeadLoad.EQ.1) then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=YearAD,CallFile=LoadFileA,HeadForm=HeadFormat, & LatF=LatF,LonF=LonF,ElvF=ElvF, & LongType=QLongType,LatMV=LatMV,LonMV=LonMV,ElvMV=ElvMV,DataMV=DataMV) else call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & CallFile=LoadFileA,HeadOnly=1,HeadForm=HeadFormat, & LatF=LatF,LonF=LonF,ElvF=ElvF, & LongType=QLongType,LatMV=LatMV,LonMV=LonMV,ElvMV=ElvMV) end if else if (QTrueQuasi.EQ.3) then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=YearAD,CallFile=LoadFileA,Hulme=HulmeA) else if (QTrueQuasi.EQ.4) then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=YearAD,CallFile=LoadFileA,HeadForm=HeadFormat, & LatF=LatF,LonF=LonF,ElvF=ElvF,PhilJ=1, & LongType=QLongType,LatMV=LatMV,LonMV=LonMV,ElvMV=ElvMV,DataMV=DataMV) end if NAStn = size(AStn,1) print*, " > Saving..." if (QDataHeadLoad.LE.1) then ! YearAD and DataA already exist QNoPer = 1 ! only save stations with genuine data else if (QDataHeadLoad.EQ.2) then ! YearAD and DataA do not already exist allocate (DataA (1,NMonth,NAStn), & YearAD (1), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertToHead: Allocation failure: DataA #####" DataA=-9999 ; YearAD=-999 QNoPer = 0 ! save all stns regardless of missing data else if (QDataHeadLoad.GT.2) then ! YearAD and DataA already exist QNoPer = 1 end if if (QDataHeadLoad.LE.2.AND.QDataHeadSave.GT.2) then allocate (DtbNormalsA(NMonth,NAStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertToHead: Allocation failure: DtbNA #####" DtbNormalsA=-9999 end if if (QDataHeadSave.LE.2) then call MakeStnInfo (StnInfoB,AStn,AStnOld,ALat,ALon,AElv,QNoPer,YearAD=YearAD,Data=DataA) else call MakeStnInfo (StnInfoB,AStn,AStnOld,ALat,ALon,AElv,QNoPer,YearAD=YearAD,Data=DataA, & DtbNormals=DtbNormalsA) end if allocate (Order(NAStn),stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertToHead: Alloc: Order #####" do XAStn=1,NAStn Order(XAStn)=XAStn end do if (QDataHeadSave.LE.1) then call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=YearAD, & Order=Order,CallFile=SaveFileA) else if (QDataHeadSave.EQ.2) then call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,HeadOnly=1, & Order=Order,CallFile=SaveFileA) else call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=YearAD, & CallFile=SaveFileA,Order=Order, DtbNormals=DtbNormalsA) end if deallocate (Order,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertToHead: Dealloc: Order #####" end subroutine ConvertToHead !******************************************************************************* subroutine ConvertToPerSet print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Enter the multiplier to apply to the data in the file:" do read (*,*,iostat=ReadStatus), DataMulti if (ReadStatus.LE.0) 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 print*, " > Select the generic .per file to save (include 'regcode'):" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") then RegSub0 = index(GivenFile,"regcode") else RegSub0 = 0 end if if (RegSub0.GT.0) exit end do !*************************************** call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=Data,YearAD=YearAD,CallFile=LoadFileA) NAStn = size(StnInfoA,1) allocate (AUni(NAStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertToPerSet: Allocation failure: A* #####" do XAStn = 1, NAStn AUni(XAStn) = GetTextFromInt(StnInfoA(XAStn,1)) end do Stem = GivenFile(01:(RegSub0-1)) Tip = GivenFile((RegSub0+7):80) call MakeBatch (Stem,Tip,AUni,SaveBatch) do XAStn = 1, NAStn NStnYear = StnInfoA(XAStn,6) - StnInfoA(XAStn,5) + 1 ! no. of years in stn record allocate (StnMon (NStnYear,12), & ! arrays for saving to .per StnSea (NStnYear, 4), & StnAnn (NStnYear), & StnYearAD(NStnYear), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertToPerSet: Allocation failure: Stn* #####" StnMon=MissVal ; StnSea=MissVal ; StnAnn=MissVal ! initialise arrays XAYear0 = 0 ! find index of first stn year in Data do XAYear0 = XAYear0 + 1 if (YearAD(XAYear0).EQ.StnInfoA(XAStn,5)) exit end do XAYear = XAYear0 - 1 do XStnYear = 1, NStnYear ! iterate by stn year XAYear = XAYear + 1 ! identify corresponding year in Data StnYearAD(XStnYear) = StnInfoA(XAStn,5) + XStnYear - 1 ! fill stn YearAD do XMonth = 1, 12 ! fill stn Monthly data file if (Data(XAYear,XMonth,XAStn).NE.DataMissVal) & StnMon(XStnYear,XMonth) = Data(XAYear,XMonth,XAStn) * DataMulti end do end do if (StatType.EQ.-1) call FillSeaAnnMin (StnYearAD,StnMon,StnSea,StnAnn) if (StatType.EQ. 0) call FillSeaAnnMean (StnYearAD,StnMon,StnSea,StnAnn) if (StatType.EQ. 1) call FillSeaAnnMax (StnYearAD,StnMon,StnSea,StnAnn) if (StatType.EQ. 2) call FillSeaAnnSum (StnYearAD,StnMon,StnSea,StnAnn) call SavePER (SaveBatch(XAStn),StnYearAD,StatType,Monthly=StnMon,Seasonal=StnSea,Annual=StnAnn,NoResponse=1) deallocate (StnMon,StnSea,StnAnn,StnYearAD,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertToPerSet: Deallocation failure: Stn* #####" end do end subroutine ConvertToPerSet !******************************************************************************* subroutine GenerateSrcFile print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") SuffixBeg = index(LoadFileA,".cts") SaveFileB = LoadFileA SaveFileB(SuffixBeg:(SuffixBeg+3)) = ".src" print*, " > Enter the source code:" do read (*,*,iostat=ReadStatus), SourceCode if (ReadStatus.LE.0) exit end do print*, " > Loading from .cts and saving to .src ..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=YearAD,CallFile=LoadFileA,Silent=1) NAYear=size(DataA,1) ; NAStn=size(DataA,3) allocate (DataB(NAYear,NMonth,NAStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertToPerSet: Allocation failure: A* #####" DataB = -9999 do XAYear = 1, NAYear do XMonth = 1, NMonth do XAStn = 1, NAStn if (DataA(XAYear,XMonth,XAStn).NE.-9999) DataB(XAYear,XMonth,XAStn) = SourceCode end do end do end do call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=DataB,YearAD=YearAD,CallFile=SaveFileB,Silent=1) end subroutine GenerateSrcFile !******************************************************************************* subroutine ConvertNewCode print*, " > Select the Mark New source code master file:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile," ") print*, " > Select the .hdr file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileB = SavePath (GivenFile,".hdr") call system ('wc -l ' // LoadFileA // ' > trashme-loadcts.txt') ! get number of lines open (3,file='trashme-loadcts.txt',status="old",access="sequential",form="formatted",action="read") read (3,"(i10)"), NAStn close (3) call system ('rm trashme-loadcts.txt') print*, " > Stations in file total: ", NAStn allocate (AStn (NAStn), & AStnOld (NAStn), & StnNameA (NAStn), & StnLocalA(NAStn), & ALat (NAStn), & ALon (NAStn), & AElv (NAStn), & StnCtyA (NAStn), & Source (NAStn), & YearAD (1), & DataA (1,NMonth,NAStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertNewCode: Allocation failure #####" LatMV=-9999 ; LonMV=-99999 ; ElvMV=-999 ; AStnOld=-999 YearAD=-999 ; DataA=-9999 ; ALat=MissVal ; ALon=MissVal ; AElv=MissVal print*, " > Loading... " open (2,file=LoadFileA,status="old",access="sequential",form="formatted",action="read") do XAStn = 1, NAStn read (2,"(i7,x,a20,4x,a9,3i6,x,a13,a19)"), AStn(XAStn),StnNameA(XAStn), & StnLocalA(XAStn),IntLat,IntLon,IntElv,StnCtyA(XAStn),Source(XAStn) if (IntLon.EQ.-9999.AND.IntLat.EQ.-9999) IntLon=LonMV if (IntLon.EQ.19990) IntLon=LonMV if (IntLat.LE.-9990) IntLat=LatMV if (IntElv.LE. -999) IntElv=ElvMV ! if (AStn(XAStn).EQ.9739017) print "(3i9)", IntLat,IntLon,IntElv ! @@@@@@@@@@@@@@@ if (IntLat.NE.LatMV) ALat(XAStn)=real(IntLat)/100.0 if (IntLon.NE.LonMV) ALon(XAStn)=real(IntLon)/100.0 if (IntElv.NE.ElvMV) AElv(XAStn)=real(IntElv) ! if (AStn(XAStn).EQ.9739017) print "(3f9.2)", ALat(XAStn),ALon(XAStn),AElv(XAStn) ! @@@@@@@@@@@@@@@ end do close (2) print*, " > Saving... " call MakeStnInfo (StnInfoA,AStn,AStnOld,ALat,ALon,AElv,0,Data=DataA,YearAD=YearAD) call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=SaveFileB,Silent=1,HeadOnly=1,Source=Source) end subroutine ConvertNewCode !******************************************************************************* subroutine AddSourceHdr print*, " > Select the .hdr file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".hdr") print*, " > Enter the source string (up to 20 char): " do read (*,*,iostat=ReadStatus), SourceStr if (ReadStatus.LE.0.AND.SourceStr.NE."") exit end do print*, " > Select the .hdr file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileB = SavePath (GivenFile,".hdr") print*, " > Loading..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=LoadFileA,HeadOnly=1) NAStn = size(StnInfoA,1) allocate (Source(NAStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AddSourceHdr: Allocation failure #####" Source = trim(SourceStr) print*, " > Saving..." call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=SaveFileB,HeadOnly=1,Source=Source) end subroutine AddSourceHdr !******************************************************************************* ! take a (processed?) WMO code file and convert to .hdr with 7-digit codes subroutine ConvertWMO print*, " > Select the WMO code file:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile," ") print*, " > Select the .hdr file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileB = SavePath (GivenFile,".hdr") print*, " > Operating..." call system ('wc -l ' // LoadFileA // ' > trashme-loadcts.txt') ! get number of lines open (3,file='trashme-loadcts.txt',status="old",access="sequential",form="formatted",action="read") read (3,"(i10)"), NAStn close (3) call system ('rm trashme-loadcts.txt') allocate (AStn (NAStn), & AStnOld (NAStn), & StnLocalA(NAStn), & DataA (1,NMonth,NAStn), & YearAD (1), & Source (NAStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertNewCode: Allocation failure #####" StnLocalA=" nocode" ; DataA=-9999 ; YearAD=-999 ; Source="NCDC MAY 2002" ; AStnOld=-999 open (2,file=LoadFileA,status="old",access="sequential",form="formatted",action="read") do XAStn = 1, NAStn read (2,"(i6)"), AStn(XAStn) end do close (2) call GetCRUtsInfo (AStn,ALat,ALon,AElv,StnNameA,StnCtyA,6) AStn = AStn * 10 ! convert from 6-digit code to 7-digit code call MakeStnInfo (StnInfoA,AStn,AStnOld,ALat,ALon,AElv,0,Data=DataA,YearAD=YearAD) call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=SaveFileB,Silent=1,HeadOnly=1,Source=Source) end subroutine ConvertWMO !******************************************************************************* subroutine ConvertLegacy print*, " > Select the legacy .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Enter the no. digits in the WMO code:" do read (*,*,iostat=ReadStatus), Digits if (ReadStatus.LE.0.AND.Digits.GE.5.AND.Digits.LE.7) exit end do print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileB = SavePath (GivenFile,".cts") call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=YearAD,CallFile=LoadFileA,Legacy=1) call GetCRUtsInfo (AStn,BLat,BLon,BElv,StnNameB,StnCtyB,Digits) NAStn = size(AStn,1) do XAStn = 1, NAStn if (ALat(XAStn).NE.MissVal.AND.BLat(XAStn).NE.MissVal .AND. & ALon(XAStn).NE.MissVal.AND.BLon(XAStn).NE.MissVal) then if (nint(ALat(XAStn)*10.0).EQ.nint(BLat(XAStn)*10.0) .AND. & nint(ALon(XAStn)*10.0).EQ.nint(BLon(XAStn)*10.0)) then ALat(XAStn)=BLat(XAStn) ; ALon(XAStn)=BLon(XAStn) end if end if end do call MakeStnInfo (StnInfoA,AStn,AStnOld,ALat,ALon,AElv,1,Data=DataA,YearAD=YearAD) call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=SaveFileB,Data=DataA,YearAD=YearAD,Silent=1) end subroutine ConvertLegacy !******************************************************************************* subroutine CorrectError print*, " > Select the .hdr file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".hdr") print*, " > Select the .hdr file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileB = SavePath (GivenFile,".hdr") print*, " > Loading..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & HeadOnly=1,CallFile=LoadFileA,Silent=1,Source=Source) NAStn = size(AStn,1) do XAStn = 1, NAStn if (StnInfoA(XAStn,7).EQ.-999) AStn(XAStn)=-999.0 if (StnInfoA(XAStn,7).GT.0.AND.StnInfoA(XAStn,7).LT.10000) AStn(XAStn)=-999.0 end do allocate (YearAD (1), & DataA (1,NMonth,NAStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CorrectError: Allocation failure #####" DataA = -9999 ; YearAD = -999 print*, " > Saving..." call MakeStnInfo (StnInfoB,AStn,AStnOld,ALat,ALon,AElv,0,YearAD=YearAD,Data=DataA) call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=AYearAD,CallFile=SaveFileB, & HeadOnly=1,Source=Source) end subroutine CorrectError !******************************************************************************* subroutine IDaddAB print*, " > Select the A (master) header file (.hdr) to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".hdr") print*, " > Select the B (extra) header file (.hdr) to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileB = LoadPath (GivenFile,".hdr") print*, " > Select the header file (.hdr) to save." do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileC = SavePath (GivenFile,".hdr") print*, " > Loading..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=LoadFileA,HeadOnly=1) call LoadCTS (StnInfoB,StnLocalB,StnNameB,StnCtyB,CallFile=LoadFileB,HeadOnly=1) NAStn = size (StnNameA,1) ; NBStn = size (StnNameB,1) ; NCStn = NBStn allocate (StnInfoC (NCStn,8), & StnLocalC(NCStn), & StnNameC (NCStn), & StnCtyC (NCStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: IDaddAB: Allocation failure: Data #####" StnInfoC = MissVal ; StnNameC = "" ; StnCtyC = "" ; StnLocalC=" nocode" PrevStn = 1 do XBStn = 1, NBStn if (StnInfoB(XBStn,1).GT.0) then XAStn = PrevStn-1 ; EquiStn = MissVal ; AddYearAD0 = MissVal ; AddYearAD1 = MissVal do XAStn = XAStn + 1 if (StnInfoA(XAStn,1).LT.StnInfoB(XBStn,1)) PrevStn = XAStn if (StnInfoA(XAStn,1).EQ.StnInfoB(XBStn,1)) EquiStn = XAStn if (StnInfoA(XAStn,1).GT.StnInfoB(XBStn,1)) exit if (XAStn.EQ.NAStn) exit end do if (EquiStn.EQ.MissVal) then AddYearAD0 = StnInfoB(XBStn,5) ; AddYearAD1 = StnInfoB(XBStn,6) else if (StnInfoA(XAStn,5).GT.StnInfoB(XBStn,5)) then AddYearAD0 = StnInfoB(XBStn,5) if (StnInfoA(XAStn,6).LT.StnInfoB(XBStn,6)) then AddYearAD1 = StnInfoB(XBStn,6) else if (StnInfoA(XAStn,5).GT.StnInfoB(XBStn,6)) then AddYearAD1 = StnInfoB(XBStn,6) else AddYearAD1 = StnInfoA(XAStn,5) - 1 end if end if else if (StnInfoA(XAStn,6).LT.StnInfoB(XBStn,6)) then AddYearAD1 = StnInfoB(XBStn,6) if (StnInfoA(XAStn,6).LT.StnInfoB(XBStn,5)) then AddYearAD0 = StnInfoB(XBStn,5) else AddYearAD0 = StnInfoA(XAStn,6) + 1 end if end if end if if (AddYearAD0.NE.MissVal) then StnLocalC(XBStn) = StnLocalB(XBStn) StnNameC (XBStn) = StnNameB (XBStn) StnCtyC (XBStn) = StnCtyB (XBStn) do XInfo = 1, 8 StnInfoC(XBStn,XInfo) = StnInfoB(XBStn,XInfo) end do StnInfoC(XBStn,5)=AddYearAD0 ; StnInfoC(XBStn,6)=AddYearAD1 end if end if end do print*, " > Saving..." call SaveCTS (StnInfoC,StnLocalC,StnNameC,StnCtyC,CallFile=SaveFileC,HeadOnly=1) end subroutine IDaddAB !******************************************************************************* subroutine CombineAB print*, " > Combine: C=A+B (=0), C=A where B has data (=1) ?" do read (*,*,iostat=ReadStatus), QCombine if (ReadStatus.LE.0.AND.QCombine.GE.0.AND.QCombine.LE.1) exit end do print*, " > Select .cts file A (priority) to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Select .cts file B to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileB = LoadPath (GivenFile,".cts") print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileC = SavePath (GivenFile,".cts") SuffixBeg = index(LoadFileB,".cts") SaveFileB = LoadFileB ; SaveFileB(SuffixBeg:SuffixBeg+3) = ".ann" print*, " > Process parallel source files (0=no,1=yes) ?" do read (*,*,iostat=ReadStatus), QSource if (ReadStatus.LE.0.AND.QSource.GE.0.AND.QSource.LE.1) exit end do if (QSource.EQ.1) then SuffixBeg=index(LoadFileA,".cts") ; LoadFileASrc=LoadFileA ; LoadFileASrc(SuffixBeg:SuffixBeg+3)=".src" SuffixBeg=index(LoadFileB,".cts") ; LoadFileBSrc=LoadFileB ; LoadFileBSrc(SuffixBeg:SuffixBeg+3)=".src" SuffixBeg=index(SaveFileC,".cts") ; SaveFileCSrc=SaveFileC ; SaveFileCSrc(SuffixBeg:SuffixBeg+3)=".src" end if print*, " > Loading..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA,Silent=1) call LoadCTS (StnInfoB,StnLocalB,StnNameB,StnCtyB,Code=BStn,OldCode=BStnOld,Lat=BLat,Lon=BLon,Elv=BElv, & Data=DataB,YearAD=BYearAD,CallFile=LoadFileB,Silent=1) call AllocateC print*, " > Combining stations..." XAStn=1 ; XBStn = 1 ; XCStn = 0 do ! combine at the station level XCStn = XCStn + 1 if (XAStn.LE.NAStn.AND.XBStn.LE.NBStn) then if (AStn(XAStn).EQ.BStn(XBStn)) QFile = 3 if (AStn(XAStn).LT.BStn(XBStn)) QFile = 1 if (AStn(XAStn).GT.BStn(XBStn)) QFile = 2 else if (XAStn.LE.NAStn) then QFile = 1 else if (XBStn.LE.NBStn) then QFile = 2 else QFile = 0 end if if (QFile.EQ.3) then CStn(XCStn)=AStn(XAStn) ; CStnOld(XCStn)=AStnOld(XAStn) ; CLat(XCStn)=ALat(XAStn) ; CLon(XCStn)=ALon(XAStn) ; CElv(XCStn)=AElv(XAStn) StnNameC(XCStn)=StnNameA(XAStn) ; StnCtyC(XCStn)=StnCtyA(XAStn) if (len_trim(StnLocalA(XAStn)).EQ.0) StnLocalC(XCStn)=StnLocalB(XBStn) if (len_trim(StnLocalC(XCStn)).EQ.0) StnLocalC(XCStn)=" nocode" if (len_trim(StnNameA(XAStn)) .EQ.0) StnNameC(XCStn)=StnNameB(XBStn) if (len_trim(StnCtyA (XAStn)) .EQ.0) StnCtyC (XCStn)=StnCtyB (XBStn) if (AElv(XAStn).EQ.-999.AND.BElv(XBStn).NE.-999) CElv(XCStn) = BElv(XBStn) MapCA(XCStn) = XAStn ; MapCB(XCStn) = XBStn XAStn = XAStn + 1 ; XBStn = XBStn + 1 else if (QFile.EQ.1) then CStn(XCStn)=AStn(XAStn) ; CStnOld(XCStn)=AStnOld(XAStn) ; CLat(XCStn)=ALat(XAStn) ; CLon(XCStn)=ALon(XAStn) ; CElv(XCStn)=AElv(XAStn) StnNameC(XCStn)=StnNameA(XAStn) ; StnCtyC(XCStn)=StnCtyA(XAStn) if (len_trim(StnLocalA(XAStn)).NE.0) StnLocalC(XCStn)=StnLocalA(XAStn) MapCA(XCStn) = XAStn XAStn = XAStn + 1 else if (QFile.EQ.2) then CStn(XCStn)=BStn(XBStn) ; CStnOld(XCStn)=BStnOld(XBStn) ; CLat(XCStn)=BLat(XBStn) ; CLon(XCStn)=BLon(XBStn) ; CElv(XCStn)=BElv(XBStn) StnNameC(XCStn)=StnNameB(XBStn) ; StnCtyC(XCStn)=StnCtyB(XBStn) if (len_trim(StnLocalB(XBStn)).NE.0) StnLocalC(XCStn)=StnLocalB(XBStn) MapCB(XCStn) = XBStn XBStn = XBStn + 1 end if if (QFile.EQ.0) print "(a,i6)", " > Total stations available: ", (XCStn-1) if (QFile.EQ.0) exit end do allocate (CYearAD (NCYear),& DataC (NCYear,NMonth,NCStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CombineAB: Allocation failure: CYearAD,DataC #####" DataC = -9999 do XCYear = 1, NCYear CYearAD(XCYear) = YearAD0 + XCYear - 1 end do call CommonVecPer (AYearAD,CYearAD,AStart,AEnd,CAStart,CAEnd) call CommonVecPer (BYearAD,CYearAD,BStart,BEnd,CBStart,CBEnd) print "(a,i4,a1,i4)", " > Period from file A: ", AYearAD(AStart),"-",AYearAD(AEnd) print "(a,i4,a1,i4)", " > Period from file B: ", BYearAD(BStart),"-",BYearAD(BEnd) print "(a,i4,a1,i4)", " > Combined period: ", CYearAD(1),"-",CYearAD(NCYear) if (QCombine.EQ.0) call CombineTheTwoAdd if (QCombine.EQ.1) call CombineTheTwoIfData if (QCombine.EQ.0) print "(a,3i10)", " > Data unique to A, B, common: ", TotA,TotB,TotAB if (QCombine.EQ.1) print "(a,3i10)", " > Okay, no-B-stn, no-B-data: ", TotAB,TotA,TotB print*, " > Saving combined .cts file..." call MakeStnInfo (StnInfoC,CStn,CStnOld,CLat,CLon,CElv,1,YearAD=CYearAD,Data=DataC) ! save .cts file call SaveCTS (StnInfoC,StnLocalC,StnNameC,StnCtyC,Data=DataC,YearAD=CYearAD,CallFile=SaveFileC,Silent=1) deallocate (DataA,DataB,AYearAD,BYearAD,StnInfoA,StnLocalA,StnNameA,StnCtyA,StnInfoB,StnLocalB,StnNameB,StnCtyB, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CombineAB: Deallocation failure: AB part 1 #####" if (QSource.EQ.1) then DataC = -9999 print*, " > Loading parallel source files..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,YearAD=AYearAD,Data=DataA,CallFile=LoadFileASrc,Silent=1) call LoadCTS (StnInfoB,StnLocalB,StnNameB,StnCtyB,YearAD=BYearAD,Data=DataB,CallFile=LoadFileBSrc,Silent=1) deallocate (StnInfoA,StnLocalA,StnNameA,StnCtyA,StnInfoB,StnLocalB,StnNameB,StnCtyB, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CombineAB: Deallocation failure: AB part 2 #####" if (QCombine.EQ.0) call CombineTheTwoAdd if (QCombine.EQ.1) call CombineTheTwoIfData print*, " > Saving parallel source file..." call SaveCTS (StnInfoC,StnLocalC,StnNameC,StnCtyC,Data=DataC,YearAD=CYearAD,CallFile=SaveFileCSrc,Silent=1) end if end subroutine CombineAB !******************************************************************************* subroutine AllocateC NAYear = size(DataA,1) ; NAStn = size(DataA,3) NBYear = size(DataB,1) ; NBStn = size(DataB,3) print "(a,i6)", " > Stations from file A: ", NAStn print "(a,i6)", " > Stations from file B: ", NBStn YearAD0 = AYearAD(1) ; if (YearAD0.GT.BYearAD(1)) YearAD0 = BYearAD(1) YearAD1 = AYearAD(NAYear) ; if (YearAD1.LT.BYearAD(NBYear)) YearAD1 = BYearAD(NBYear) NCYear = YearAD1 - YearAD0 + 1 ; NCStn = NAStn + NBStn allocate (CStn (NCStn), & ! make station-specific allocations CStnOld (NCStn), & CLat (NCStn), & CLon (NCStn), & CElv (NCStn), & StnNameC (NCStn), & StnLocalC(NCStn), & StnCtyC (NCStn), & MapCA (NCStn), & MapCB (NCStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocateC: Allocation failure: CStn #####" CStn=-999 ; CLat=-999 ; CLon=-9999 ; CElv=-999 ; MapCA=-999 ; MapCB=-999 StnNameC="" ; StnCtyC="" ; StnLocalC=" nocode" end subroutine AllocateC !******************************************************************************* subroutine CombineTheTwoAdd TotA=0 ; TotB=0 ; TotAB=0 do XCStn = 1, NCStn if (MapCA(XCStn).NE.-999) then do XAYear = AStart, AEnd XCYear = CAStart + XAYear - AStart do XMonth = 1, NMonth if (DataA(XAYear,XMonth,MapCA(XCStn)).NE.-9999) then TotA = TotA + 1 DataC (XCYear,XMonth,XCStn) = DataA (XAYear,XMonth,MapCA(XCStn)) end if end do end do end if if (MapCB(XCStn).NE.-999) then do XBYear = BStart, BEnd XCYear = CBStart + XBYear - BStart do XMonth = 1, NMonth if (DataB(XBYear,XMonth,MapCB(XCStn)).NE.-9999) then if (DataC(XCYear,XMonth,XCStn).EQ.-9999) then DataC (XCYear,XMonth,XCStn) = DataB (XBYear,XMonth,MapCB(XCStn)) TotB = TotB + 1 else TotA = TotA - 1 ; TotAB = TotAB + 1 end if end if end do end do end if end do end subroutine CombineTheTwoAdd !******************************************************************************* subroutine CombineTheTwoIfData TotA=0 ; TotB=0 ; TotAB=0 do XCStn = 1, NCStn if (MapCA(XCStn).NE.-999) then if (MapCB(XCStn).NE.-999) then do XAYear = AStart, AEnd XCYear = CAStart + XAYear - AStart XBYear = BStart + XCYear - CBStart do XMonth = 1, NMonth if (DataA(XAYear,XMonth,MapCA(XCStn)).NE.-9999) then if (DataB(XBYear,XMonth,MapCB(XCStn)).NE.-9999) then TotAB = TotAB + 1 DataC (XCYear,XMonth,XCStn) = DataA (XAYear,XMonth,MapCA(XCStn)) else TotB = TotB + 1 end if end if end do end do else TotA = TotA + 1 end if end if end do end subroutine CombineTheTwoIfData !******************************************************************************* subroutine DescribeAPer print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Select the .per file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileB = SavePath (GivenFile,".per") print*, " > Loading..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=Data,YearAD=YearAD,CallFile=LoadFileA) NAStn = size(StnInfoA,1) ; NAYear = size(YearAD,1) allocate (SumsPer(NAYear,17), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DescribeAPer: Allocation failure #####" SumsPer = 0 do XAYear = 1, NAYear do XMonth = 1, NMonth do XAStn = 1, NAStn if (Data(XAYear,XMonth,XAStn).NE.-9999) SumsPer(XAYear,XMonth)=SumsPer(XAYear,XMonth)+1 end do end do end do do XSeasonYear = 1, NAYear do XSeason = 1, 4 do XSeasonMonth = (XSeason*3),(XSeason*3)+2 XMonth=XSeasonMonth ; XAYear=XSeasonYear if (XMonth.GT.12) then XMonth=XMonth-12 ; XAYear=XAYear+1 end if if (XAYear.LE.NAYear) then SumsPer(XSeasonYear,12+XSeason)=SumsPer(XSeasonYear,12+XSeason)+SumsPer(XAYear,XMonth) else SumsPer(XSeasonYear,12+XSeason)=-999.0 end if end do if (SumsPer(XSeasonYear,12+XSeason).NE.-999.0) & SumsPer(XSeasonYear,12+XSeason)=SumsPer(XSeasonYear,12+XSeason)/3.0 end do end do do XAYear = 1, NAYear do XMonth = 1, 12 SumsPer(XAYear,17)=SumsPer(XAYear,17)+SumsPer(XAYear,XMonth) end do if (SumsPer(XAYear,17).NE.-9999) SumsPer(XAYear,17)=SumsPer(XAYear,17)/12.0 end do LineFormat='(i5,12f9.1,5f9.1)' call SavePER (SaveFileB,YearAD,2,AllData=SumsPer,NoResponse=1,CallLineFormat=LineFormat) end subroutine DescribeAPer !******************************************************************************* subroutine DescribeAAnn print*, " > Select the .cts or .dtb file to load:" do read (*,*,iostat=ReadStatus), GivenFile SuffixBeg = index(GivenFile,".cts") ; if (SuffixBeg.GT.0) FileSuffix = ".cts" SuffixBeg = index(GivenFile,".dtb") ; if (SuffixBeg.GT.0) FileSuffix = ".dtb" if (ReadStatus.LE.0.AND.(FileSuffix.EQ.".cts".OR.FileSuffix.EQ.".dtb")) exit end do LoadFileA = LoadPath (GivenFile,FileSuffix) print*, " > Select the .ann file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileB = SavePath (GivenFile,".ann") print*, " > Operating ..." if (FileSuffix.EQ.'.cts') then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn, & Data=DataA,YearAD=YearAD,CallFile=LoadFileA) else call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld, & Lat=ALat,Lon=ALon,Elv=AElv,DtbNormals=DtbNormalsA, & Data=DataA,YearAD=YearAD,CallFile=LoadFileA,silent=1) end if NAStn = size(StnInfoA,1) ; NAYear = size(YearAD,1) call ClassifyContinent print*, " > Total valid data: ", TotA call SaveANN (SaveFileB,YearAD,ColTitles,SumsPer,DecPlaceN=1) end subroutine DescribeAAnn !******************************************************************************* ! CAREFUL! this is called both from DescribeAAnn and Anomalise subroutine ClassifyContinent NCty=MasterSize() allocate (CtyName (NCty), & CtyFinal (NCty), & CtyCode0 (NCty), & CtyCode1 (NCty), & CtyReg (NCty), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ClassifyContinent: Allocation failure #####" call LoadMasterCty (CtyName,CtyFinal,CtyCode0,CtyCode1,CtyReg) allocate (SumsPer(NAYear,12), & ColTitles(12), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ClassifyContinent: Allocation failure #####" SumsPer = 0 ; ColTitles = RegTitles do XAStn = 1, NAStn if (AStn(XAStn).NE.MissVal) then XCty=0 ; XReg=0 do XCty=XCty+1 if (trim(StnCtyA(XAStn)).EQ.trim(CtyName(XCty))) XReg=CtyReg(XCty) if (XReg.NE.0) exit if (XCty.EQ.NCty) exit end do do XAYear = 1, NAYear do XMonth = 1, NMonth if (DataA(XAYear,XMonth,XAStn).NE.-9999) then SumsPer(XAYear,1)=SumsPer(XAYear,1)+1 if (XReg.GE.1.AND.XReg.LE.11) SumsPer(XAYear,(XReg+1))=SumsPer(XAYear,(XReg+1))+1 end if end do end do end if end do TotA = 0 do XAYear = 1, NAYear TotA = TotA + SumsPer(XAYear,1) do XReg = 1, 12 SumsPer(XAYear,XReg)=SumsPer(XAYear,XReg)/12.0 end do end do deallocate (CtyName,CtyFinal,CtyCode0,CtyCode1,CtyReg, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ClassifyContinent: Deallocation failure #####" end subroutine ClassifyContinent !******************************************************************************* subroutine OperateAk print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Select the operation (A/k=1, A*k=2, A-k=3, A+k=4, sqrt=5, **k=6, abs=7): " do read (*,*,iostat=ReadStatus), QOperation if (ReadStatus.LE.0 .AND. QOperation.GE.1 .AND. QOperation.LE.7) exit end do Constant = -999.0 if (QOperation.NE.5.AND.QOperation.NE.7) then print*, " > Select the constant: " do read (*,*,iostat=ReadStatus), Constant if (ReadStatus.LE.0) exit end do end if call EnquireRestrict print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileC = SavePath (GivenFile,".cts") print*, " > Operating ..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=Data,YearAD=YearAD,CallFile=LoadFileA) NAStn = size(StnInfoA,1) ; NAYear = size(YearAD,1) do XAStn = 1, NAStn do XAYear = 1, NAYear do XMonth = 1, 12 if (Data(XAYear,XMonth,XAStn).NE.-9999) then Data(XAYear,XMonth,XAStn) = & OpAwithB (real(Data(XAYear,XMonth,XAStn)),Constant,QOperation) if (QRestrict.Eq.1.OR.QRestrict.Eq.3) then if (Data(XAYear,XMonth,XAStn).LT.Min) Data(XAYear,XMonth,XAStn) = MinImpose end if if (QRestrict.Eq.2.OR.QRestrict.Eq.3) then if (Data(XAYear,XMonth,XAStn).GT.Max) Data(XAYear,XMonth,XAStn) = MaxImpose end if end if end do end do end do call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=Data,YearAD=YearAD,CallFile=SaveFileC) end subroutine OperateAk !******************************************************************************* subroutine OperateAB print*, " > Select .cts file A to load (priority for headers):" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Select the operation (A/B=1, A*B=2, A-B=3, A+B=4): " do read (*,*,iostat=ReadStatus), QOperation if (ReadStatus.LE.0 .AND. QOperation.GE.1 .AND. QOperation.LE.4) exit end do print*, " > Select .cts file B to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileB = LoadPath (GivenFile,".cts") call EnquireRestrict print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileC = SavePath (GivenFile,".cts") print*, " > Manipulate parallel .src files ? (0=no,1=yes)" do read (*,*,iostat=ReadStatus), QSource if (ReadStatus.LE.0.AND.QSource.GE.0.AND.QSource.LE.1) exit end do if (QSource.EQ.1) then LoadFileASrc = LoadFileA SuffixBeg = index(LoadFileASrc,".cts") ; LoadFileASrc(SuffixBeg:SuffixBeg+3) = ".src" SaveFileCSrc = SaveFileC SuffixBeg = index(SaveFileCSrc,".cts") ; SaveFileCSrc(SuffixBeg:SuffixBeg+3) = ".src" end if print*, " > Loading ..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA) call LoadCTS (StnInfoB,StnLocalB,StnNameB,StnCtyB,Code=BStn,OldCode=BStnOld,Lat=BLat,Lon=BLon,Elv=BElv, & Data=DataB,YearAD=BYearAD,CallFile=LoadFileB) if (QSource.EQ.1) call LoadCTS (StnInfoC,StnLocalC,StnNameC,StnCtyC, & Data=DataC,YearAD=CYearAD,CallFile=LoadFileASrc) NAStn = size(StnInfoA,1) ; NAYear = size(AYearAD,1) NBStn = size(StnInfoB,1) ; NBYear = size(BYearAD,1) call CommonVecPer (AYearAD,BYearAD,AStart,AEnd,BStart,BEnd) print "(a,2i5)", " > Common period:", AYearAD(AStart),AYearAD(AEnd) XBStn = 1 ; XAStn = 1 do ! write (99,"(a,2i8)"), "ITERATION:", AStn(XAStn),BStn(XBStn) ! @@@@@@@@@@@@@@@@@@@@@@@@@@@@ if (AStn(XAStn).EQ.BStn(XBStn)) then do XAYear = 1, NAYear if (XAYear.LT.AStart.OR.XAYear.GT.AEnd) then ! write (99,"(a,i5)"), "OUTRANGE:", AYearAD(XAYear) ! @@@@@@@@@@@@@@@@@@@@@@@@@@@@ do XMonth = 1, NMonth DataA(XAYear,XMonth,XAStn) = -9999 ; if (QSource.EQ.1) DataC(XAYear,XMonth,XAStn) = -9999 end do else XBYear = XAYear - AStart + BStart ! write (99,"(a,2i5)"), "IN-RANGE:", AYearAD(XAYear),BYearAD(XBYear) ! @@@@@@@@@@@@@@@@@@@@@@@@@@@@ do XMonth = 1, NMonth if (DataA(XAYear,XMonth,XAStn).NE.-9999.AND.DataB(XBYear,XMonth,XBStn).NE.-9999) then OpVal = OpAwithB (real(DataA(XAYear,XMonth,XAStn)), & real(DataB(XBYear,XMonth,XBStn)),QOperation) DataA(XAYear,XMonth,XAStn) = nint(OpVal) ! write (99,"(a,2i5)"), XMonth,DataA(XAYear,XMonth,XAStn),DataB(XBYear,XMonth,XBStn), & ! ! @@@@@@@@@@@@@@@@@@@@@@@@@@@@ if (QRestrict.Eq.1.OR.QRestrict.Eq.3) then if (DataA(XAYear,XMonth,XAStn).LT.Min) DataA(XAYear,XMonth,XAStn) = MinImpose end if if (QRestrict.Eq.2.OR.QRestrict.Eq.3) then if (DataA(XAYear,XMonth,XAStn).GT.Max) DataA(XAYear,XMonth,XAStn) = MaxImpose end if else DataA(XAYear,XMonth,XAStn) = -9999 ; if (QSource.EQ.1) DataC(XAYear,XMonth,XAStn) = -9999 end if end do end if end do XAStn = XAStn + 1 ; XBStn = XBStn + 1 else if (AStn(XAStn).LT.BStn(XBStn)) then ! write (99,"(a,i8)"), "REMOVING:", AStn(XAStn) ! @@@@@@@@@@@@@@@@@@@@@@@@@@@@ do XAYear = 1, NAYear do XMonth = 1, NMonth DataA(XAYear,XMonth,XAStn) = -9999 ; if (QSource.EQ.1) DataC(XAYear,XMonth,XAStn) = -9999 end do end do XAStn = XAStn + 1 else if (AStn(XAStn).GT.BStn(XBStn)) then ! write (99,"(a,i8)"), "IGNORING:", BStn(XBStn) ! @@@@@@@@@@@@@@@@@@@@@@@@@@@@ XBStn = XBStn + 1 end if if (XAStn.GT.NAStn.OR.XBStn.GT.NBStn) exit end do print*, " > Saving ..." call MakeStnInfo (StnInfoC,AStn,AStnOld,ALat,ALon,AElv,1,YearAD=AYearAD,Data=DataA) ! save .cts file call SaveCTS (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=AYearAD,CallFile=SaveFileC) if (QSource.EQ.1) call SaveCTS (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=DataC,YearAD=AYearAD,CallFile=SaveFileCSrc) end subroutine OperateAB !******************************************************************************* subroutine EnquireRestrict print*, " > Impose min (=1), max (=2), both (=3), neither (=0):" do read (*,*,iostat=ReadStatus), QRestrict if (ReadStatus.LE.0.AND.QRestrict.GE.0.AND.QRestrict.LE.3) exit end do if (QRestrict.EQ.1.OR.QRestrict.EQ.3) then print*, " > Enter the minimum value to accept, and value to impose:" do read (*,*,iostat=ReadStatus), Min,MinImpose if (ReadStatus.LE.0) exit end do end if if (QRestrict.EQ.2.OR.QRestrict.EQ.3) then print*, " > Enter the maximum value to accept, and value to impose:" do read (*,*,iostat=ReadStatus), Max,MaxImpose if (ReadStatus.LE.0) exit end do end if end subroutine EnquireRestrict !******************************************************************************* subroutine GetLatLongRect print*, " > Select the .cts or .dtb file to load:" do read (*,*,iostat=ReadStatus), GivenFile SuffixBeg = index(GivenFile,".cts") ; if (SuffixBeg.GT.0) FileSuffix = ".cts" SuffixBeg = index(GivenFile,".dtb") ; if (SuffixBeg.GT.0) FileSuffix = ".dtb" if (ReadStatus.LE.0.AND.(FileSuffix.EQ.".cts".OR.FileSuffix.EQ.".dtb")) exit end do LoadFileA = LoadPath (GivenFile,FileSuffix) print*, " > Enter the min,max lat and min,max long:" do read (*,*,iostat=ReadStatus), Lat0,Lat1,Lon0,Lon1 if (ReadStatus.LE.0.AND.Lat0.GE.-90.AND.Lat1.LE.90.AND.Lat1.GE.Lat0) then if (Lon0.GE.-180.AND.Lon0.LE.180.AND.Lon1.GE.-180.AND.Lon1.LE.180) then if (Lon0.GT.Lon1) then print*, " > We note that the selected rectangle crosses the Date Line." QCrossDL = 1 else QCrossDL = 0 end if else print*, " > Lat/long boundaries are unacceptable. Re-try." ReadStatus = 1 end if else print*, " > Lat/long boundaries are unacceptable. Re-try." ReadStatus = 1 end if if (ReadStatus.LE.0) exit end do print*, " > Enter the min,max elevation (-999,-999: no restriction): " do read (*,*,iostat=ReadStatus), Elv0,Elv1 if (ReadStatus.LE.0) then if (Elv0.EQ.-999.AND.Elv1.EQ.-999) then Elv0 = -100000 ; Elv1 = 100000 else if (Elv0.GT.Elv1) then print*, " > Elevation boundaries are unacceptable. Re-try." ReadStatus = 1 end if end if end if if (ReadStatus.LE.0) exit end do if (FileSuffix.EQ.".cts") print*, " > Select the .cts file to save:" if (FileSuffix.EQ.".dtb") print*, " > Select the .dtb file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileA = SavePath (GivenFile,FileSuffix) !*************************************** print*, " > Loading..." if (FileSuffix.EQ.".cts") then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld, & Lat=ALat,Lon=ALon,Elv=AElv, & Data=Data,YearAD=AYearAD,CallFile=LoadFileA) else call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld, & Lat=ALat,Lon=ALon,Elv=AElv, & Data=Data,DtbNormals=DtbNormalsA,YearAD=AYearAD,CallFile=LoadFileA) end if NAStn = size(StnInfoA,1) allocate (StnInfoB(NAStn,8), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GetLatLongRect: alloc StnInfoB #####" where (ALat.LT.Lat0.OR.ALat.GT.Lat1) AStn = -999 if (Elv0.NE.-999.OR.Elv1.EQ.-999) then where (AElv.LT.Elv0.OR.AElv.GT.Elv1) AStn = -999 end if if (QCrossDL.EQ.0) then where (ALon.LT.(Lon0).OR.ALon.GT.(Lon1)) AStn = -999 else where (ALon.GT.(Lon1).AND.ALon.LT.(Lon0)) AStn = -999 end if print*, " > Saving..." if (FileSuffix.EQ.".cts") then call MakeStnInfo (StnInfoB,AStn,AStnOld,ALat,ALon,AElv,1, & YearAD=AYearAD,Data=Data) call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,Data=Data, & YearAD=AYearAD,CallFile=SaveFileA) else call MakeStnInfo (StnInfoB,AStn,AStnOld,ALat,ALon,AElv,1, & YearAD=AYearAD,Data=Data,DtbNormals=DtbNormalsA) call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,Data=Data, & YearAD=AYearAD,CallFile=SaveFileA,DtbNormals=DtbNormalsA) end if end subroutine GetLatLongRect !******************************************************************************* subroutine TruncateDate print*, " > Select the .cts or .dtb file to load:" do read (*,*,iostat=ReadStatus), GivenFile SuffixBeg = index(GivenFile,".cts") ; if (SuffixBeg.GT.0) FileSuffix = ".cts" SuffixBeg = index(GivenFile,".dtb") ; if (SuffixBeg.GT.0) FileSuffix = ".dtb" if (ReadStatus.LE.0.AND.(FileSuffix.EQ.".cts".OR.FileSuffix.EQ.".dtb")) exit end do LoadFileA = LoadPath (GivenFile,FileSuffix) print*, " > Loading..." if (FileSuffix.EQ.".cts") then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA) else call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,DtbNormals=DtbNormalsA,YearAD=AYearAD,CallFile=LoadFileA) end if NAYear = size(AYearAD,1) NAStn = size(DataA, 3) print "(a,i4,a1,i4)", " > The loaded file extends: ", AYearAD(1), "-", AYearAD(NAYear) print*, " > Select the initial year, month in the truncated file:" do read (*,*,iostat=ReadStatus), YearAD0,Month0 if (ReadStatus.LE.0.AND.Month0.GE.1.AND.Month0.LE.12) exit end do print*, " > Select the final year, month in the truncated file:" do read (*,*,iostat=ReadStatus), YearAD1,Month1 if (ReadStatus.LE.0.AND.Month1.GE.1.AND.Month1.LE.12.AND.YearAD1.GE.YearAD0) exit end do if (FileSuffix.EQ.".cts") print*, " > Select the .cts file to save:" if (FileSuffix.EQ.".dtb") print*, " > Select the .dtb file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileB = SavePath (GivenFile,FileSuffix) print*, " > Truncating..." NBYear = YearAD1 - YearAD0 + 1 allocate (BYearAD(NBYear), & DataB (NBYear,NMonth,NAStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: TruncateDate: Allocation failure: BYearAD,DataB #####" DataB = -9999 do XBYear = 1, NBYear BYearAD(XBYear) = YearAD0 + XBYear - 1 end do call CommonVecPer (AYearAD,BYearAD,AStart,AEnd,BStart,BEnd) do XBYear = BStart, BEnd XAYear = AStart + XBYear - BStart do XMonth = 1, NMonth if (XBYear.EQ.BStart.AND.XMonth.LT.Month0) then ! leave DataB blank else if (XBYear.EQ.BEnd .AND.XMonth.GT.Month1) then ! leave DataB blank else do XAStn = 1, NAStn DataB(XBYear,XMonth,XAStn) = DataA(XAYear,XMonth,XAStn) end do end if end do end do print*, " > Saving..." call MakeStnInfo (StnInfoB,AStn,AStnOld,ALat,ALon,AElv,1,YearAD=BYearAD,Data=DataB) if (FileSuffix.EQ.".cts") then call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,Data=DataB,YearAD=BYearAD,CallFile=SaveFileB) else call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,Data=DataB,DtbNormals=DtbNormalsA, & YearAD=BYearAD,CallFile=SaveFileB) end if end subroutine TruncateDate !******************************************************************************* subroutine QCImplicitStdev print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Process parallel source file? (1=no,2=yes) ?" do read (*,*,iostat=ReadStatus), QSource if (ReadStatus.LE.0.AND.QSource.GE.1.AND.QSource.LE.2) exit end do print*, " > Enter the min. no. of values required to calc a stdev:" do read (*,*,iostat=ReadStatus), ThreshStdev if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do print*, " > If no stdev, keep (=1) or reject (=2) data ?" do read (*,*,iostat=ReadStatus), QNoStdev if (ReadStatus.LE.0.AND.QNoStdev.GE.1.AND.QNoStdev.LE.2) exit end do print*, " > Enter the no. of stdevs at which to flag data:" do read (*,*,iostat=ReadStatus), ThreshReject if (ReadStatus.LE.0.AND.ThreshReject.GT.0) exit end do print*, " > Reject (=1) or manually check (=2) flagged data ?" do read (*,*,iostat=ReadStatus), QManCheck if (ReadStatus.LE.0.AND.QManCheck.GE.1.AND.QManCheck.LE.2) exit end do if (QManCheck.EQ.2) then print*, " > Set earliest, latest years to check manually (-999=no limit):" do read (*,*,iostat=ReadStatus), CheckYear0, CheckYear1 ! if (CheckYear0.NE.-999.AND.(CheckYear0.LT.YearAD(1).OR. & ! CheckYear0.GT.YearAD(NAYear))) ReadStatus=1 ! if (CheckYear1.NE.-999.AND.(CheckYear1.LT.YearAD(1).OR. & ! CheckYear1.GT.YearAD(NAYear))) ReadStatus=1 if (CheckYear0.NE.-999.AND.CheckYear1.NE.-999.AND.CheckYear0.GT.CheckYear1) & ReadStatus=1 if (ReadStatus.LE.0) exit end do end if print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileB = SavePath (GivenFile,".cts") if (QSource.EQ.2) then LoadFileASrc=LoadfileA SuffixBeg=index(LoadFileASrc,".cts") LoadFileASrc(SuffixBeg:SuffixBeg+3)=".src" SaveFileBSrc=SaveFileB SuffixBeg=index(SaveFileBSrc,".cts") SaveFileBSrc(SuffixBeg:SuffixBeg+3)=".src" end if print*, " > Loading, processing ..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,Oldcode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=YearAD,CallFile=LoadFileA) if (QSource.EQ.2) then call LoadCTS (StnInfoB,StnLocalB,StnNameB,StnCtyB, & Data=DataASrc,YearAD=BYearAD,CallFile=LoadFileASrc) deallocate (StnInfoB,StnLocalB,StnNameB,StnCtyB,BYearAD, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: QCImplicitStdev: Allocation failure: St* #####" end if NAYear = size(DataA,1) ; NAStn = size(DataA,3) allocate (StnAnn (NAYear), & LogStdev(1,NMonth,NAStn), & LogMeans(1,NMonth,NAStn), & Stdev (1,NMonth,NAStn), & Means (1,NMonth,NAStn), & CYearAD (1), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: QCImplicitStdev: Allocation failure: St* #####" ThreshOpCalc = 100.0 * (real(NAYear) - ThreshStdev) / real(NAYear) do XMonth = 1, NMonth do XAStn = 1, NAStn do XAYear = 1, NAYear StnAnn(XAYear) = DataA(XAYear,XMonth,XAStn) end do Means(1,XMonth,XAStn) = OpCalcMean (StnAnn,NAYear,ThreshOpCalc,CallMissVal=-9999.0) Stdev(1,XMonth,XAStn) = OpCalcStDev (StnAnn,NAYear,ThreshOpCalc,2,CallMissVal=-9999.0) end do end do allocate (LogPass(NAYear+1,NMonth+1), & LogMiss(NAYear+1,NMonth+1), & LogSkip(NAYear+1,NMonth+1), & LogFail(NAYear+1,NMonth+1), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: QCImplicitStdev: Allocation failure: DataB* #####" LogPass=0 ; LogFail=0 ; LogSkip=0 ; LogMiss=0 do XAStn = 1, NAStn ThreshLo=-9999 ; ThreshHi=-9999 ; SeqStatus=0.0 do XMonth = 1, NMonth if (Stdev(1,XMonth,XAStn).NE.-9999.AND.Means(1,XMonth,XAStn).NE.-9999) then ThreshLo(XMonth)=Means(1,XMonth,XAStn)-(Stdev(1,XMonth,XAStn)*ThreshReject) ThreshHi(XMonth)=Means(1,XMonth,XAStn)+(Stdev(1,XMonth,XAStn)*ThreshReject) end if end do do XAYear = 1, NAYear InRange=1 if (CheckYear0.NE.-999.AND.YearAD(XAYear).LT.CheckYear0) InRange=0 if (CheckYear1.NE.-999.AND.YearAD(XAYear).GT.CheckYear1) InRange=0 do XMonth = 1, NMonth if (DataA(XAYear,XMonth,XAStn).NE.-9999) then if (ThreshLo(XMonth).NE.-9999.AND.Stdev(1,XMonth,XAStn).GT.0.0) then Excess = (DataA(XAYear,XMonth,XAStn)-Means(1,XMonth,XAStn))/Stdev(1,XMonth,XAStn) SeqStatus=SeqStatus+abs(Excess)-ThreshReject+1 if (DataA(XAYear,XMonth,XAStn).GE.ThreshLo(XMonth) & .AND.DataA(XAYear,XMonth,XAStn).LE.ThreshHi(XMonth)) then LogPass(XAYear,XMonth) = LogPass(XAYear,XMonth) + 1 else write(99,"(i7,x,a20,i3,i5,i6,2f6.2,2f8.2)"),AStn(XAStn),StnNameA(XAStn),XMonth,& YearAD(XAYear),DataA(XAYear,XMonth,XAStn),Excess,SeqStatus, & ThreshLo(XMonth),ThreshHi(XMonth) if (QManCheck.EQ.1.OR.InRange.EQ.0.OR.abs(Excess).GT.real(ThreshReject+1)) then DataA (XAYear,XMonth,XAStn) = -9999 if (QSource.EQ.2) DataASrc(XAYear,XMonth,XAStn) = -9999 LogFail(XAYear,XMonth) = LogFail(XAYear,XMonth) + 1 else if (SeqStatus.GT.4.0) then call ManualCheck else LogPass(XAYear,XMonth) = LogPass(XAYear,XMonth) + 1 end if end if if (SeqStatus.GT.0) SeqStatus=SeqStatus-0.5 if (SeqStatus.LT.0) SeqStatus=0.0 else ! no stdev calculable if (QNoStdev.EQ.1) then LogSkip(XAYear,XMonth) = LogSkip(XAYear,XMonth) + 1 else DataA (XAYear,XMonth,XAStn) = -9999 if (QSource.EQ.2) DataASrc(XAYear,XMonth,XAStn) = -9999 LogSkip(XAYear,XMonth) = LogSkip(XAYear,XMonth) + 1 end if end if else ! data is missing LogMiss(XAYear,XMonth) = LogMiss(XAYear,XMonth) + 1 end if end do end do end do print*, " > Saving QC'd data ..." call MakeStnInfo (StnInfoB,AStn,AStnOld,ALat,ALon,AElv,1,YearAD=YearAD,Data=DataA) call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=YearAD, & CallFile=SaveFileB,Silent=1) if (QSource.EQ.2) call SaveCTS (StnInfoB,StnLocalA,StnNameA,StnCtyA,Data=DataASrc, & YearAD=YearAD,CallFile=SaveFileBSrc,Silent=1) print*, " > Saving means and stdev to extra log files ..." CYearAD = YearAD(1) Means=Means*10.0 ; LogMeans=Means Stdev=Stdev*10.0 ; LogStdev=Stdev call system ('rm /cru/mikeh1/f709762/scratch/log/log-opcruts-means.cts') call system ('rm /cru/mikeh1/f709762/scratch/log/log-opcruts-stdev.cts') call MakeStnInfo (StnInfoC,AStn,AStnOld,ALat,ALon,AElv,1,YearAD=CYearAD,Data=LogMeans) call SaveCTS (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=LogMeans,YearAD=CYearAD,CallFile=LogMeansFile,Silent=1) deallocate (StnInfoC, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: QCImplicitStdev: Deallocation failure: StnInfoC* #####" call MakeStnInfo (StnInfoC,AStn,AStnOld,ALat,ALon,AElv,1,YearAD=CYearAD,Data=LogStdev) call SaveCTS (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=LogStdev,YearAD=CYearAD,CallFile=LogStdevFile,Silent=1) print*, " > Saving QC statistics to main log file ..." do XLog = 1, 4 if (XLog.EQ.1) LogAny => LogPass if (XLog.EQ.2) LogAny => LogMiss if (XLog.EQ.3) LogAny => LogSkip if (XLog.EQ.4) LogAny => LogFail do XAYear = 1, NAYear do XMonth = 1, NMonth LogAny(XAYear,NMonth+1) = LogAny(XAYear,NMonth+1) + LogAny(XAYear,XMonth) end do end do do XMonth = 1, NMonth do XAYear = 1, NAYear LogAny(NAYear+1,XMonth) = LogAny(NAYear+1,XMonth) + LogAny(XAYear,XMonth) end do end do do XMonth = 1, NMonth LogAny(NAYear+1,NMonth+1) = LogAny(NAYear+1,NMonth+1) + LogAny(NAYear+1,XMonth) end do write (99,"(a4,a)"),LogName(XLog), & " Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec TOT" do XAYear = 1, NAYear write (99,"(i4,12i6,i7)"), YearAD(XAYear),(LogAny(XAYear,XMonth),XMonth=1,NMonth+1) end do write (99,"(a4,12i6,i7)"), "TOT ",(LogAny(NAYear+1,XMonth),XMonth=1,NMonth+1) write (99,"(a)"), " " nullify(LogAny) end do end subroutine QCImplicitStdev !******************************************************************************* subroutine ManualCheck print "(a,i8,i6,x,a20,x,a13,i3,i5,f8.2)", " > ", AStn(XAStn),XAStn,StnNameA(XAStn), & StnCtyA(XAStn),XMonth,YearAD(XAYear),Excess !print "(a4,12f7.2)", "LO ", (ThreshLo(XBMonth),XBMonth=1,12) !print "(a4,12f7.2)", "HI ", (ThreshHi(XBMonth),XBMonth=1,12) print*, " > Reject single (=2), sequence (=1), or none (=0) ?" do read (*,*,iostat=ReadStatus), QReject if (ReadStatus.LE.0.AND.QReject.GE.0.AND.QReject.LE.2) exit end do if (QReject.EQ.0) then LogPass(XAYear,XMonth) = LogPass(XAYear,XMonth) + 1 else if (QReject.EQ.2) then DataA (XAYear,XMonth,XAStn) = -9999 if (QSource.EQ.2) DataASrc(XAYear,XMonth,XAStn) = -9999 LogFail(XAYear,XMonth) = LogFail(XAYear,XMonth) + 1 else if (QReject.EQ.1) then print*, " > Enter the first mon+yr, last mon+yr to reject: " do read (*,*,iostat=ReadStatus), XMonth0,XYear0,XMonth1,XYear1 if (ReadStatus.LE.0.AND.XYear1.GE.XYear0.AND.XMonth0.GE.1.AND.XMonth0.LE.12 & .AND.XMonth1.GE.1.AND.XMonth1.LE.12 & .AND.XYear0.GE.YearAD(1).AND.XYear1.LE.YearAD(NAYear)) exit end do do XBYear=(XYear0-YearAD(1)+1),(XYear1-YearAD(1)+1) do XBMonth=1,NMonth if (XBYear.EQ.(XYear0-YearAD(1)+1).AND.XBMonth.LT.XMonth0) then else if (XBYear.EQ.(XYear1-YearAD(1)+1).AND.XBMonth.GT.XMonth1) then else if (DataA(XBYear,XBMonth,XAStn).NE.-9999) then DataA(XBYear,XBMonth,XAStn) = -9999 if (QSource.EQ.2) DataASrc(XBYear,XBMonth,XAStn) = -9999 LogFail(XAYear,XMonth) = LogFail(XAYear,XMonth) + 1 if (XBYear.LT.XAYear.OR.(XBYear.EQ.XAYear.AND.XBMonth.LT.XMonth)) then LogPass(XAYear,XMonth) = LogPass(XAYear,XMonth) - 1 else if (XBYear.EQ.XAYear.AND.XBMonth.EQ.XMonth) then else LogMiss(XAYear,XMonth) = LogMiss(XAYear,XMonth) - 1 end if end if end if end do end do end if ! LastCheck = XAStn end subroutine ManualCheck !******************************************************************************* subroutine Anomalise print*, " > This software is now a separate program: anomdtb.f90" end subroutine Anomalise !******************************************************************************* subroutine FindClosest print*, " > Select the .cts or .dtb file to load:" do read (*,*,iostat=ReadStatus), GivenFile SuffixBeg = index(GivenFile,".cts") ; if (SuffixBeg.GT.0) FileSuffix = ".cts" SuffixBeg = index(GivenFile,".dtb") ; if (SuffixBeg.GT.0) FileSuffix = ".dtb" if (ReadStatus.LE.0.AND.(FileSuffix.EQ.".cts".OR.FileSuffix.EQ.".dtb")) exit end do LoadFileA = LoadPath (GivenFile,FileSuffix) print*, " > Enter the lat and long: " do read (*,*,iostat=ReadStatus), Lat0,Lon0 if (ReadStatus.LE.0.AND.Lat0.GE.-90.AND.Lat0.LE.90.AND.Lon0.GE.-180.AND.Lon0.LE.180) exit end do print*, " > Find the closest N stations. Specify N." do read (*,*,iostat=ReadStatus), NBStn if (ReadStatus.LE.0.AND.NBStn.GE.1) exit end do print*, " > Restrict to stns with data in period: beg,end (-999=don't restrict):" do read (*,*,iostat=ReadStatus), YearAD0,YearAD1 if (ReadStatus.LE.0) exit end do print*, " > Loading, processing ..." if (FileSuffix.EQ.".cts") then call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,oldcode=AStnOld, & Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA) else call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,oldcode=AStnOld, & Lat=ALat,Lon=ALon,Elv=AElv,DtbNormals=DtbNormalsA, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA) end if NAYear = size(DataA,1) ; NAStn = size(DataA,3) allocate (Scatter(NAStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: FindClosest: Allocation failure: Scatter #####" Scatter = MissVal do XAStn = 1, NAStn if ( (YearAD0.EQ.MissVal.AND.YearAD1.EQ.MissVal).OR. & (StnInfoA(XAStn,5).LE.YearAD0.AND.StnInfoA(XAStn,6).GE.YearAD0) .OR. & (StnInfoA(XAStn,5).LE.YearAD1.AND.StnInfoA(XAStn,6).GE.YearAD1) .OR. & (StnInfoA(XAStn,5).GE.YearAD0.AND.StnInfoA(XAStn,6).LE.YearAD1) ) then if (ALat(XAStn).NE.MissVal.AND.ALon(XAStn).NE.MissVal) & Scatter(XAStn) = GetDistance (ALat(XAStn),ALon(XAStn),Lat0,Lon0) end if end do do XBStn = 1, NBStn Limit = 100000.0 do XAStn = 1, NAStn if (Scatter(XAStn).NE.MissVal.AND.Scatter(XAStn).LT.Limit) then Limit = Scatter(XAStn) ; XCStn = XAStn end if end do print "(i7,2f8.2,i6,x,a20,x,a13,2(x,i4),f8.2)", AStn(XCStn),ALat(XCStn),ALon(XCStn),nint(AElv(XCStn)), & StnNameA(XCStn),StnCtyA(XCStn),StnInfoA(XCStn,5),StnInfoA(XCStn,6),Scatter(XCStn) Scatter(XCStn) = MissVal end do end subroutine FindClosest !******************************************************************************* subroutine MultiplyCodes print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileA = SavePath (GivenFile,".cts") print*, " > Enter the factor by which to multiply codes: " do read (*,*,iostat=ReadStatus), Factor if (ReadStatus.LE.0) exit end do print*, " > Multiply positive (>0) codes only ? (0=no,1=yes) " do read (*,*,iostat=ReadStatus), QPosOnly if (ReadStatus.LE.0.AND.QPosOnly.GE.0.AND.QPosOnly.LE.1) exit end do print*, " > Store the original code as 'old code' ? (0=no,1=yes)" do read (*,*,iostat=ReadStatus), QStoreOld if (ReadStatus.LE.0.AND.QStoreOld.GE.0.AND.QStoreOld.LE.1) exit end do print*, " > Operating..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,oldcode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA) NAStn = size(DataA,3) if (QStoreOld.EQ.1) then do XAStn = 1, NAStn AStnOld(XAStn) = AStn(XAStn) end do end if do XAStn = 1, NAStn if (QPosOnly.EQ.0.OR.AStn(XAStn).GT.0) AStn(XAStn) = nint(real(AStn(XAStn)) * Factor) end do call MakeStnInfo (StnInfoC,AStn,AStnOld,ALat,ALon,AElv,0,YearAD=AYearAD,Data=DataA) call SaveCTS (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=AYearAD,CallFile=SaveFileA) end subroutine MultiplyCodes !******************************************************************************* subroutine SyncCtsSrc print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") SubBeg=index(LoadFileA,".cts") LoadFileB=LoadFileA ; LoadFileB(SubBeg:(SubBeg+3))=".src" call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA) call LoadCTS (StnInfoB,StnLocalB,StnNameB,StnCtyB, & Data=DataB,YearAD=BYearAD,CallFile=LoadFileB) NAYear = size(DataA,1) ; NAStn = size(DataA,3) ; Log1=0 ; Log2=0 ; XInfo=MultiSource do XAStn = 1, NAStn do XAYear = 1, NAYear do XMonth = 1, NMonth if (DataA(XAYear,XMonth,XAStn).EQ.DataMissVal.AND. & DataB(XAYear,XMonth,XAStn).NE.DataMissVal) then Log1=Log1+1 write (99,"(6i8)"), 1,AYearAD(XAYear),XMonth,StnInfoA(XAStn,1), & DataA(XAYear,XMonth,XAStn),DataB(XAYear,XMonth,XAStn) DataB(XAYear,XMonth,XAStn) = DataMissVal else if (DataA(XAYear,XMonth,XAStn).NE.DataMissVal.AND. & DataB(XAYear,XMonth,XAStn).EQ.DataMissVal) then Log2=Log2+1 write (99,"(6i8)"), 2,AYearAD(XAYear),XMonth,StnInfoA(XAStn,1), & DataA(XAYear,XMonth,XAStn),DataB(XAYear,XMonth,XAStn) DataB(XAYear,XMonth,XAStn) = XInfo else if (DataB(XAYear,XMonth,XAStn).NE.DataMissVal) then XInfo=DataB(XAYear,XMonth,XAStn) end if end do end do end do if (Log1.EQ.0.AND.Log2.EQ.0) then print*, " > The .cts and .src files are already in sync." else if (Log1.GT.0) print "(a,i10)", " > X. Miss data but valid src:", Log1 if (Log2.GT.0) print "(a,i10)", " > Y. Valid data but miss src:", Log2 end if if (Log1.GT.0) then print*, " > Select the corrected .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileA = SavePath (GivenFile,".cts") SubBeg=index(SaveFileA,".cts") SaveFileB=SaveFileA ; SaveFileB(SubBeg:(SubBeg+3))=".src" call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=AYearAD,CallFile=SaveFileA) call SaveCTS (StnInfoB,StnLocalB,StnNameB,StnCtyB,Data=DataB,YearAD=BYearAD,CallFile=SaveFileB) end if end subroutine SyncCtsSrc !******************************************************************************* subroutine ImpossibleElev print*, " > Select the file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do StrLen=len_trim(GivenFile) FileSuffix=GivenFile((StrLen-3):StrLen) LoadFileA = LoadPath (GivenFile,FileSuffix) StrLen=len_trim(LoadFileA) print*, " > Select the file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do FileSuffix=LoadFileA((StrLen-3):StrLen) SaveFileA = SavePath (GivenFile,FileSuffix) if (LoadFileA((StrLen-3):StrLen).EQ.'.hdr') then if (index(LoadFileA,"master").NE.0) then print*, " > Loading master .hdr file..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=LoadFileA,HeadOnly=1,Elv=AElv) else print*, " > Loading accessions .hdr file..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=LoadFileA,HeadOnly=1,Elv=AElv, & SrcCode=StnSrcCodeA,SrcSuffix=StnSrcSuffixA,SrcDate=StnSrcDateA) end if else print*, " > Loading database file..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=YearAD,Elv=AElv, & CallFile=LoadFileA,DtbNormals=DtbNormalsA) end if NAStn=size(StnInfoA,1) do XAStn = 1, NAStn if (AElv(XAStn).NE.-999.AND.(AElv(XAStn).LT.-500.OR.AElv(XAStn).GT.6000)) then AElv(XAStn)=MissVal ; StnInfoA(XAStn,4)=MissVal ; OpEn=OpEn+1 end if end do print "(a,i5)", " > Stns corrected total: ", nint(OpEn) if (LoadFileA((StrLen-3):StrLen).EQ.'.hdr') then if (index(LoadFileA,"master").NE.0) then print*, " > Saving master .hdr file..." call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=SaveFileA,HeadOnly=1) else print*, " > Saving accessions .hdr file..." call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=SaveFileA,HeadOnly=1, & SrcCode=StnSrcCodeA,SrcSuffix=StnSrcSuffixA,SrcDate=StnSrcDateA) end if else print*, " > Saving database file..." call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=YearAD, & CallFile=SaveFileA,DtbNormals=DtbNormalsA) end if end subroutine ImpossibleElev !******************************************************************************* ! convert degrees and minutes in .cts header lines to degrees and hundedths subroutine ConvertDegHun print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileA = SavePath (GivenFile,".cts") print*, " > Operating..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA, & Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA) NAStn = size(DataA,3) do XAStn = 1, NAStn if (ALat(XAStn).NE.-999.0) then OpDiff = mod (ALat(XAStn),1.0) OpVal = ALat(XAStn) - OpDiff OpDiff = OpDiff / 0.60 ALat(XAStn) = OpVal + OpDiff end if if (ALon(XAStn).NE.-999.0) then OpDiff = mod (ALon(XAStn),1.0) OpVal = ALon(XAStn) - OpDiff OpDiff = OpDiff / 0.60 ALon(XAStn) = OpVal + OpDiff end if end do call MakeStnInfo (StnInfoC,AStn,AStnOld,ALat,ALon,AElv,0,YearAD=AYearAD,Data=DataA) call SaveCTS (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=AYearAD,CallFile=SaveFileA) end subroutine ConvertDegHun !******************************************************************************* subroutine MultiplyNRM print*, " > We also looks out for dodgy data missing values (-999)." print*, " > Select the .nrm file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".nrm") print*, " > Select the .nrm file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileA = SavePath (GivenFile,".nrm") print*, " > Select the constant: " do read (*,*,iostat=ReadStatus), Factor if (ReadStatus.LE.0) exit end do print*, " > Operating..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=LoadFileA,Silent=1, & NmlSrc=NmlSrc,NmlInc=NmlInc,NmlData=Normals) NAStn = size(StnNameA,1) do XAStn = 1, NAStn do XMonth = 1, NMonth if (Normals(XMonth,XAStn).EQ.-999) then Normals(XMonth,XAStn) = DataMissVal else if (Normals(XMonth,XAStn).NE.DataMissVal) then Normals(XMonth,XAStn) = nint(real(Normals(XMonth,XAStn))*Factor) end if end do end do call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,CallFile=SaveFileA,Silent=1, & NmlSrc=NmlSrc,NmlInc=NmlInc,NmlData=Normals) end subroutine MultiplyNRM !******************************************************************************* ! convert different variable databases (.dtb to .cts) ! option 1 = .rhm to .vap subroutine ConvertVariableDtb print*, " > Select the conversion (1=rhm->vap):" do read (*,*,iostat=ReadStatus), QMerge if (ReadStatus.LE.0.AND.QMerge.GE.1.AND.QMerge.LE.1) exit end do print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileC = SavePath (GivenFile,".cts") if (QMerge.EQ.1) DatabaseFilter="/tyn1/tim/data/cruts/database/rhm.??????????.dtb" call GetBatch (DatabaseFilter,DatabaseBatch,Silent=1) NBatch = size(DatabaseBatch,1) DatabaseFileL = DatabaseBatch(NBatch) ! i.e. most recently dated file Date=DatabaseFileL(36:43) ; TimeVal=DatabaseFileL(44:47) call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=AYearAD, & CallFile=DatabaseFileL,Silent=1) NAStn = size(StnNameA,1) ; NAYear = size(AYearAD,1) print "(a,2(a2,a1),a2,a4,a2,a1,a2,a,i7,a)", " > Database file at ",Date(7:8),".",Date(5:6),& ".",Date(3:4)," at ",TimeVal(1:2),":",TimeVal(3:4)," has ",(NAstn)," stns." deallocate (StnInfoA,StnLocalA,StnNameA,StnCtyA,AYearAD,DatabaseBatch,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertVariableDtb: Deallocation failure: 1 #####" DatabaseSrcFileL = DatabaseFileL SubBeg = index(DatabaseSrcFileL,".dtb") DatabaseSrcFileL(SubBeg:SubBeg+3) = ".dts" call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataC,YearAD=AYearAD,CallFile=DatabaseSrcFileL,Silent=1) deallocate (StnInfoA,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertVariableDtb: Deallocation failure: 2 #####" if (QMerge.EQ.1) DatabaseFilter="/tyn1/tim/data/cruts/database/tmp.??????????.dtb" call GetBatch (DatabaseFilter,DatabaseBatch,Silent=1) NBatch = size(DatabaseBatch,1) DatabaseFileL = DatabaseBatch(NBatch) ! i.e. most recently dated file Date=DatabaseFileL(36:43) ; TimeVal=DatabaseFileL(44:47) call LoadCTS (StnInfoB,StnLocalB,StnNameB,StnCtyB,Code=BStn,Lat=BLat,Lon=BLon,Elv=BElv, & Data=DataB,YearAD=BYearAD,CallFile=DatabaseFileL,Silent=1) NBStn = size(StnNameB,1) ; NBYear = size(BYearAD,1) print "(a,2(a2,a1),a2,a4,a2,a1,a2,a,i7,a)", " > Database file at ",Date(7:8),".",Date(5:6),& ".",Date(3:4)," at ",TimeVal(1:2),":",TimeVal(3:4)," has ",(NBStn)," stns." deallocate (StnInfoB,DatabaseBatch,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertVariableDtb: Deallocation failure: 3 #####" call CommonVecPer (AYearAD,BYearAD,AStart,AEnd,BStart,BEnd) print "(a,2i5)", " > Common period:", AYearAD(AStart),AYearAD(AEnd) XAStn=1 ; XBStn=1 do if (AStn(XAStn).EQ.BStn(XBStn)) then do XAYear = 1, NAYear XBYear = XAYear-AStart+BStart if (XBYear.LT.0.OR.XBYear.GT.NBYear) then do XMonth = 1, NMonth DataA(XAYear,XMonth,XAStn) = DataMissVal DataC(XAYear,XMonth,XAStn) = DataMissVal end do else do XMonth = 1, NMonth if (DataA(XAYear,XMonth,XAStn).GE.0.AND.DataA(XAYear,XMonth,XAStn).LE.1000.AND. & DataB(XBYear,XMonth,XBStn).NE.DataMissVal) then if (QMerge.EQ.1) then ! rhm + tmp --> vap if (DataB(XBYear,XMonth,XBStn).GE.2) then ! assume Tw>0 OpVal = 17.38 * (real(DataB(XBYear,XMonth,XBStn))/10.0) OpVal = OpVal / (239.0 + (real(DataB(XBYear,XMonth,XBStn))/10.0)) else ! assume Tw<0 OpVal = 22.44 * (real(DataB(XBYear,XMonth,XBStn))/10.0) OpVal = OpVal / (272.4 + (real(DataB(XBYear,XMonth,XBStn))/10.0)) end if OpVal = 6.107 * exp(OpVal) OpVal = OpVal * real(DataA(XAYear,XMonth,XAStn)) / 1000.0 DataA(XAYear,XMonth,XAStn) = nint(OpVal*10.0) ! we also retain DataC end if else DataA(XAYear,XMonth,XAStn) = DataMissVal DataC(XAYear,XMonth,XAStn) = DataMissVal end if end do end if end do XAStn=XAStn+1 ; XBStn=XBStn+1 else if (AStn(XAStn).LT.BStn(XBStn)) then AStn(XAStn)=MissVal XAStn=XAStn+1 else if (AStn(XAStn).GT.BStn(XBStn)) then XBStn=XBStn+1 end if if (XAStn.GT.NAStn.OR.XBStn.GT.NBStn) exit end do print*, " > Saving to .cts and .src ..." call MakeStnInfo (StnInfoC,AStn,AStnOld,ALat,ALon,AElv,1,YearAD=AYearAD,Data=DataA) call SaveCTS (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=AYearAD,CallFile=SaveFileC) SuffixBeg=index(SaveFileC,".cts") SaveFileC=SaveFileC(1:SuffixBeg-1) // ".src" call SaveCTS (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=DataC,YearAD=AYearAD,CallFile=SaveFileC) end subroutine ConvertVariableDtb !******************************************************************************* ! convert different variable .cts file (.cts to .cts) ! option 1 = .snh to .spc subroutine ConvertVariableCts print*, " > Select the conversion (1=snh->spc):" do read (*,*,iostat=ReadStatus), QMerge if (ReadStatus.LE.0.AND.QMerge.GE.1.AND.QMerge.LE.1) exit end do print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") print*, " > Process parallel source file? (1=no,2=yes) ?" do read (*,*,iostat=ReadStatus), QSource if (ReadStatus.LE.0.AND.QSource.GE.1.AND.QSource.LE.2) exit end do print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileA = SavePath (GivenFile,".cts") print*, " > Operating..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA, & Code=AStn,OldCode=AStnOld,Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA) NAYear=size(DataA,1) ; NAStn=size(DataA,3) if (QSource.EQ.2) then LoadFileASrc=LoadfileA SuffixBeg=index(LoadFileASrc,".cts") LoadFileASrc(SuffixBeg:SuffixBeg+3)=".src" SaveFileASrc=SaveFileA SuffixBeg=index(SaveFileA,".cts") SaveFileASrc(SuffixBeg:SuffixBeg+3)=".src" call LoadCTS (StnInfoB,StnLocalB,StnNameB,StnCtyB, & Data=DataASrc,YearAD=BYearAD,CallFile=LoadFileASrc) deallocate (StnInfoB,StnLocalB,StnNameB,StnCtyB,BYearAD, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertVariableCts: dealloc: B* #####" end if if (QMerge.EQ.1) then allocate (MonthLengths(NAYear,NMonth), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertVariableCts: alloc: ML #####" do XAStn=1,NAStn if (ALat(XAStn).NE.MissVal) then LatRad=ALat(XAStn)*3.1415927/180.0 do XMonth=1,NMonth ! calc max snh per day Numer=sin(Ephemeris(XMonth))*sin(LatRad)*(0.0-1.0) Denom=cos(Ephemeris(XMonth))*cos(LatRad) if ((Numer/Denom).GE.-1.AND.(Numer/Denom).LE.1) then TheoryMax(XMonth) = 8.0 * acos (Numer/Denom) else if (Numer.GT.0) then TheoryMax(XMonth) = 0.0 else TheoryMax(XMonth) = 24.0 end if end do call GetMonthLengths (AYearAD,MonthLengths) do XAYear=1,NAYear do XMonth=1,NMonth if (DataA(XAYear,XMonth,XAStn).NE.DataMissVal) then if (TheoryMax(XMonth).GT.0) then Numer=real(DataA(XAYear,XMonth,XAStn))/10.0 Denom=TheoryMax(XMonth)*real(MonthLengths(XAYear,XMonth)) DataA(XAYear,XMonth,XAStn) = nint(1000.0 * Numer / Denom) if (DataA(XAYear,XMonth,XAStn).LT.0.OR. & DataA(XAYear,XMonth,XAStn).GT.1010) then DataA (XAYear,XMonth,XAStn) = DataMissVal if (QSource.EQ.2) DataASrc(XAYear,XMonth,XAStn) = DataMissVal else if (DataA(XAYear,XMonth,XAStn).GT.1000) then DataA(XAYear,XMonth,XAStn) = 1000 end if else DataA (XAYear,XMonth,XAStn) = DataMissVal if (QSource.EQ.2) DataASrc(XAYear,XMonth,XAStn) = DataMissVal end if end if end do end do ! write (99,"(i7,x,a20,f8.2,12f6.1)"), AStn(XAStn),StnNameA(XAStn),ALat(XAStn), & ! (TheoryMax(XMonth),XMonth=1,NMonth) else ! if no lat cannot calc theoretical max snh AStn(XAStn)=MissVal end if end do deallocate (MonthLengths, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertVariableCts: dealloc: ML #####" end if call MakeStnInfo (StnInfoC,AStn,AStnOld,ALat,ALon,AElv,1,YearAD=AYearAD,Data=DataA) call SaveCTS (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=AYearAD,CallFile=SaveFileA) if (QSource.EQ.2) call SaveCTS & (StnInfoC,StnLocalA,StnNameA,StnCtyA,Data=DataASrc,YearAD=AYearAD,CallFile=SaveFileASrc) end subroutine ConvertVariableCts !******************************************************************************* ! option 34 subroutine PruneSource print*, " > Select the .cts file to load:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do LoadFileA = LoadPath (GivenFile,".cts") SubBeg = index(LoadFileA,".cts",.TRUE.) LoadFileB = LoadFileA ; LoadFileB(SubBeg:(SubBeg+3)) = ".src" print*, " > Select the .cts file to save:" do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0.AND.GivenFile.NE."") exit end do SaveFileA = SavePath (GivenFile,".cts") SubBeg = index(SaveFileA,".cts",.TRUE.) SaveFileB = SaveFileA ; SaveFileB(SubBeg:(SubBeg+3)) = ".src" print*, " > Select the source code to remove:" do read (*,*,iostat=ReadStatus), SrcRemove if (ReadStatus.LE.0) exit end do print*, " > Loading..." call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=DataASrc,YearAD=AYearAD, & CallFile=LoadFileB,Silent=1) deallocate (StnInfoA,StnLocalA,StnNameA,StnCtyA,AYearAD,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### PruneSource: dealloc load src #####" call LoadCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Code=AStn,OldCode=AStnOld, & Lat=ALat,Lon=ALon,Elv=AElv, & Data=DataA,YearAD=AYearAD,CallFile=LoadFileA,Silent=1) deallocate (StnInfoA,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### PruneSource: dealloc load cts #####" NAYear = size(DataA,1) ; NMonth=12 ; NAStn = size(DataA,3) ; Log01=0 print*, " > Processing..." do XAYear=1,NAYear do XMonth=1,NMonth do XAStn=1,NAStn if (DataASrc(XAYear,XMonth,XAStn).EQ.SrcRemove) then DataASrc(XAYear,XMonth,XAStn) = DataMissVal DataA (XAYear,XMonth,XAStn) = DataMissVal Log01=Log01+1 end if end do end do end do print "(a,i10)", " > Made changes to data: ", Log01 print*, " > Saving..." call MakeStnInfo (StnInfoA,AStn,AStnOld,ALat,ALon,AElv,1,YearAD=AYearAD, & Data=DataA,Silent=1) call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=DataA,YearAD=AYearAD, & CallFile=SaveFileA,Silent=1) call SaveCTS (StnInfoA,StnLocalA,StnNameA,StnCtyA,Data=DataASrc,YearAD=AYearAD, & CallFile=SaveFileB,Silent=1) end subroutine PruneSource !******************************************************************************* subroutine Finish print* close (99) end subroutine Finish !******************************************************************************* end program OpCRUts