Program vertical_differences_soundings
!
! The programs reads time series data from two text files with soundings data
! and writes the difference time series to the output file in a ODB compatible format  
!
! Although the name hints calculation of vertical differences between two levels,
! other types of differences can also be calculated.  
!  
! Jouni Räisänen, University of Helsinki, August 2023
!
!----------------------------------------------------------------------
! Input files (text format)
!----------------------------------------------------------------------
!                        
! INFILE_1: The first data file (time series for one level and location)
! INFILE_2: The second data file (time series for one level and location)
!
! The differences INFILE_1 - INFILE_2 are calculated  
!
! In both files, the first line is a header. The other lines include:
!
!             1) year
!             2) month        
!             3) day        
!             4) hour
!             5) longitude
!             6) latitude
!             7) station code
!             8) variable code
!             9) level  
!             10) data value
!
! If (lgruan.eq.true), the station code is assumed to be a 3-character string
! Otherwise, it is assumed to be an integer.
!
!----------------------------------------------------------------------
! Output file (ODB compatible text format)
!----------------------------------------------------------------------
!  
! OUTFILE: the difference time series (INFILE_1 minus INFILE_2)
!  
! The first line is a header. The other lines include
!
!             1) year
!             2) month        
!             3) day        
!             4) hour
!             5) longitude
!             6) latitude
!             7) station code
!             8) variable code
!             9) data value
!
! (NB: no level value is written) 
!
!----------------------------------------------------------------------
!
! Namelist parameters:
!
!  infile_1 = 1st input file
!  infile_2 = 2nd input file
!  outfile = output file
!  miss = missing value code (default: -9.99e6)
!         all data values f for which |f| >= |miss| are interpreted as missing   
!  lgruan = if .true., station code is assumed to be 3-character string
!           if .false., station codes is assumed to be integer
!-----------------------------------------------------------------
!    
implicit none
!
character*160 :: infile_1,infile_2 ! input files
character*160 :: outfile ! output file
character*300 :: line,line1,line2 ! lines read from / written to text file
integer :: year1,month1,day1,hour1 ! year,month,day and hour read from infile_1
integer :: year2,month2,day2,hour2 ! year,month,day and hour read from infile_2
integer :: time1 ! hour1+24*day1+31*24*month1+31*24*12*(year1-1800)     
integer :: time2 ! hour2+24*day2+31*24*month2+31*24*12*(year2-1800)     
integer :: timeprev ! the previous time in the difference time series
character*3 :: station_char ! station code as string (GRUAN?)
integer :: station_int ! station code as integer (RHARM?)
real :: longitude,latitude ! longitude and laitude
integer :: variable ! variable code
real :: level ! level as read from input files (not used)
real :: f1,f2,f ! single data values
real :: miss=-9.99e6 ! missing value codes
logical :: lgruan ! if .true., assume 3-char station code (otherwise integer)
!
namelist/param/infile_1,infile_2,outfile,miss,lgruan
!
read(*,nml=param)
!
! Open the input and output files:
!
open(unit=1,file=trim(infile_1),form='formatted')
open(unit=2,file=trim(infile_2),form='formatted')
open(unit=11,file=trim(outfile),form='formatted')
!
! Read the header lines from the two input files
!
read(1,*)
read(2,*)
!
! Write the header to the output file. There is no 'level' because the result is a single-level variable
!
if(lgruan)then
write(11,*)&
     'year@hdr:integer ','month@hdr:integer ','day@hdr:integer ','hour@hdr:integer ',&
     'longitude@hdr:real ','latitude@hdr:real ','station@hdr:string ','variable@body:integer ',&
     'value@body:real '
else
write(11,*)&
     'year@hdr:integer ','month@hdr:integer ','day@hdr:integer ','hour@hdr:integer ',&
     'longitude@hdr:real ','latitude@hdr:real ','station@hdr:integer ','variable@body:integer ',&
     'value@body:real '

endif
!
! Main loop. Search the times for which there is data in both infile_1 and infile_2
! and write the differences to outfile
!
time1=0
time2=0
timeprev=0

do while (.true.)
1  if(time1.le.timeprev.or.time1.lt.time2)then
      read(1,'(A300)',err=10,end=10)line
      call compress_line(line,line1,300)
      write(*,*)'line=',line
      write(*,*)'line1=',line1      
      if(lgruan)then
         read(line1,*)year1,month1,day1,hour1,longitude,latitude,station_char,&
              variable,level,f1
      else
         read(line1,*)year1,month1,day1,hour1,longitude,latitude,station_int,&
              variable,level,f1         
      endif      
      time1=hour1+24*day1+31*24*month1+31*24*12*(year1-1800)     
      goto 1
   endif   
2  if(time2.lt.time1)then
     read(2,'(A300)',err=10,end=10)line
     call compress_line(line,line2,300)
     if(lgruan)then
        read(line2,*)year2,month2,day2,hour2,longitude,latitude,station_char,&
             variable,level,f2
     else
        read(line2,*)year2,month2,day2,hour2,longitude,latitude,station_int,&
             variable,level,f2        
     endif     
     time2=hour2+24*day2+31*24*month2+31*24*12*(year2-1800)
     goto 1
   endif
   if(time1.ne.time2)then ! Just a test. The previous code should ensure that this
                          ! line is only reached when time1=time1
      write(*,*)'Something wrong: time1,time2=',time1,time2
      stop
   endif
   timeprev=time1
   !
   ! Only write the output for those times when there is non-missing 
   ! data in both input files.
   !
   if(max(abs(f1),abs(f2)).ge.abs(miss))then  
      write(*,*)'Data missing:',year1,month1,day1,hour1,f1,f2
   else
      if(lgruan)then
         write(11,'(I4,1X,I2,1X,I2,1X,I2,2F16.6,1X,A3,1X,I2,F16.6)')&
         year1,month1,day1,hour1,longitude,latitude,station_char,variable,f1-f2
      else         
         write(11,'(I4,1X,I2,1X,I2,1X,I2,2F16.6,1X,I6,1X,I2,F16.6)')&
         year1,month1,day1,hour1,longitude,latitude,station_int,variable,f1-f2
      endif      
   endif   
enddo
10 continue
close(1)
close(2)

end program vertical_differences_soundings
!
! Copy the string 'line' to 'line1', excluding
! hyphens.
!
subroutine compress_line(line,line1,n)
  implicit none
  integer :: i,j,n  
  character :: line(n)
  character :: line1(n)
  line1=' '
  j=0
  do i=1,n
     if(line(i).ne."'")then       
        j=j+1
        line1(j)=line(i)
     endif     
  enddo
  return
end subroutine compress_line
