SUBROUTINE read_surface_obs(infile,blackfile,                           & 5,2
           maxsta,istart,atime,n_meso_g,                                &
           n_meso_pos,n_sao_g,n_sao_pos_g,n_sao_b,n_sao_pos_b,n_obs_g,  &
           n_obs_pos_g,n_obs_b,n_obs_pos_b,stn,obstype,lat,lon,elev,wx, &
           t,td,dd,ff,ddg,ffg,pstn,pmsl,alt,kloud,ceil,lowcld,cover,rad, &
           idp3,store_emv,store_amt,store_hgt,vis,obstime,istatus)
!
!*******************************************************************************
!
!    Routine to read mesonet and SAO data for LAPS that has been written
!    into the .LSO file by the 'get_surface_obs' routine.
!
!    Changes:
!            P. Stamus       12-30-92  Original version.
!                            01-07-93  Add/change obs counters.
!                            01-08-93  Add read_header entry.
!            K. Brewster     12-20-99  Moved the initialization of
!                                      cloud amts to missing to
!                                      inside of station read loop
!
!    Input/Output:
!
!     Variable        Var type   I/O   Description
!    ----------      ---------- ----- -------------
!     infile            A*80      I    Directory where LSO file is.
!     maxsta             I        I    Max Number of stations allowed.
!     atime             A*24      O    Data time in dd-mmm-yyyy hh:mm
!     n_meso_g           I        O    Number of FSL mesonet stations
!     n_meso_pos         I        O    Total number mesonet stations psbl
!     n_sao_g            I        O    Number of SAOs in the laps grid
!     n_sao_pos_g        I        O    Total num. of SAOs psbl in laps grid
!     n_sao_b            I        O    Number of SAOs in the box
!     n_sao_pos_b        I        O    Total num of SAOs psbl in the box
!     n_obs_g            I        O    Number of obs in the laps grid
!     n_obs_pos_g        I        O    Total num of obs psbl in the laps grid
!     n_obs_b            I        O    Number of obs in the box
!     n_obs_pos_b        I        O    Total num of obs possible in the box
!     stn               A*3 A     O    Station names (array)
!     lat                RA       O    Station latitude (deg)
!     lon                RA       O    Station longitude (deg)
!     elev               RA       O    Station elevation (m)
!     obstype           A*8 A     O    Observation type (SA, SP, ASOS, etc)
!     obstime            IA       O    Time of observation (hhmm)
!     wx                A*8 A     O    Observed weather
!     t                  RA       O    Temperature (F)
!     td                 RA       O    Dewpoint (F)
!     dd                 RA       O    Wind direction (deg)
!     ff                 RA       O    Wind speed (kt)
!     ddg                RA       O    Gust wind direction (deg)
!     ffg                RA       O    Gust wind speed (kt)
!     pstn               RA       O    Station pressure (mb)
!     pmsl               RA       O    MSL pressure (mb)
!     alt                RA       O    Altimeter setting (mb)
!     kloud              IA       O    Number of cloud layers...max of 5.
!     ceil               RA       O    Ceiling height (m)
!     lowcld             RA       O    Height lowest cloud (m)
!     cover              RA       O    Cloud cover (tenths)
!     vis                RA       O    Visibility (miles)
!     rad                RA       O    Solar radiation.
!     idp3               IA       O    3-h coded pressure change (e.g.,608)
!     store_emv         A*1 A     O    Cloud descriptors: ea. layer, ea. stn
!     store_amt         A*4 A     O    Cloud layer coverage.
!     store_hgt          RA       O    Height of each cloud layer.
!     istatus            I        O    Status flag: 1 = normal
!                                                  -1 = file not found
!                                                  -2 = Arrays too small
!
!    User Notes:
!
!    1.  Arrays should be dimensioned 'maxsta' in the calling program,
!        with maxsta *at least* 120 (for CO domain).
!
!    2.  Pressures are stored as reported, except that altimeters are
!        converted to millibars.
!
!    3.  The 'kloud' variable tells whether there are clouds and how
!        many layers if there are:
!            a) kloud = 0    means   No cloud DATA (but NOT "no clouds").
!            b) kloud = 1    means   CLR or 1 cloud layer.  A height is
!                                    given for CLR which is the maximum valid
!                                    height of the observation (automatic
!                                    stations have limited valid heights).
!            c) kloud = 2-5  means   Two to five cloud layers.
!
!    4.  Thin obscured (-X) is a cloud layer and is given a 'badflag'
!        height, since it is not supposed to have a height (you're supposed
!        to be able to see other clouds and/or sky).
!
!*******************************************************************************
!
  IMPLICIT NONE
  INTEGER :: maxsta
  INTEGER :: istart
  INTEGER :: misval
  PARAMETER       (misval=999)
  REAL :: badflag
  PARAMETER       (badflag = -99.9)
!
  REAL :: lat(maxsta),lon(maxsta),elev(maxsta)
  REAL :: t(maxsta),td(maxsta)
  REAL :: dd(maxsta),ff(maxsta)
  REAL :: ddg(maxsta),ffg(maxsta)
  REAL :: pstn(maxsta),pmsl(maxsta),alt(maxsta)
  REAL :: store_hgt(maxsta,5)
  REAL :: ceil(maxsta),lowcld(maxsta),cover(maxsta)
  REAL :: vis(maxsta),rad(maxsta)
!
  INTEGER :: obstime(maxsta),kloud(maxsta),idp3(maxsta)
!
  CHARACTER (LEN=132) :: infile
  CHARACTER (LEN=132) :: blackfile
  CHARACTER (LEN=24) :: atime
  CHARACTER (LEN=5) :: stn(maxsta)
  CHARACTER (LEN=8) :: obstype(maxsta)
  CHARACTER (LEN=8) :: wx(maxsta)
  CHARACTER (LEN=1) :: store_emv(maxsta,5)
  CHARACTER (LEN=4) :: store_amt(maxsta,5)
!
  INTEGER :: n_meso_g,n_meso_pos,n_sao_g,n_sao_pos_g
  INTEGER :: n_sao_b,n_sao_pos_b,n_obs_g,n_obs_pos_g
  INTEGER :: n_obs_b,n_obs_pos_b
  INTEGER :: istatus
!
  INTEGER :: i,k,ios,ii
!
!.....  Start here.  Set the status to nothing, zero out the cloud storage.
!
  istatus = 0
!
!.....  Open the file.  Check for a 'file not found' or other problem.
!
  OPEN(1,IOSTAT=ios,FILE=trim(infile),STATUS='old',                     &
       ACCESS='sequential',FORM='formatted')
  IF(ios /= 0) THEN     ! error during read
    istatus = -1
    WRITE(6,650) infile
    650       FORMAT(' +++ ERROR opening: ',a80,' +++')
    WRITE(6,651) ios
    651       FORMAT('     IOS code = ',i5)
    RETURN
  END IF
!
!.....  File open...first read the header.
!
  READ(1,900) atime,              & ! data time
           n_meso_g,          & ! # of mesonet stations
           n_meso_pos,        & ! total # mesonet stations possible
           n_sao_g,           & ! # of saos in the laps grid
           n_sao_pos_g,       & ! total # of saos possible in laps grid
           n_sao_b,           & ! # of saos in the box
           n_sao_pos_b,       & ! total # of saos possible in the box
           n_obs_g,           & ! # of obs in the laps grid
           n_obs_pos_g,       & ! total # of obs psbl in the laps grid
           n_obs_b,           & ! # of obs in the box
           n_obs_pos_b        ! total # of obs possible in the box
  900     FORMAT(1X,a24,10(1X,i4))
!wdt tmp
!  1900     FORMAT("XXX header:",1X,a24,10(1X,i4))
!  WRITE(*,1900) atime,              & ! data time
!           n_meso_g,          & ! # of mesonet stations
!           n_meso_pos,        & ! total # mesonet stations possible
!           n_sao_g,           & ! # of saos in the laps grid
!           n_sao_pos_g,       & ! total # of saos possible in laps grid
!           n_sao_b,           & ! # of saos in the box
!           n_sao_pos_b,       & ! total # of saos possible in the box
!           n_obs_g,           & ! # of obs in the laps grid
!           n_obs_pos_g,       & ! total # of obs psbl in the laps grid
!           n_obs_b,           & ! # of obs in the box
!           n_obs_pos_b        ! total # of obs possible in the box
!
!.....  Error trapping for too many stations for array size.
!
  IF(n_obs_b > maxsta) THEN
    PRINT 990, maxsta,n_obs_b,atime
    990       FORMAT(' +++ ERROR in READ_SURFACE_OBS: maxsta = ',i8,/, &
           ' but there are ',i8,' stations in the ',a24,' obs file.',/)
    PRINT *,'    Increase the value of "maxsta" and try again.'
    istatus = -2
    RETURN
  END IF
!
!.....  Now read the station data.
!
  DO i=1,n_obs_b
    k=i+istart-1
    READ(1,901) stn(k),lat(k),lon(k),elev(k),obstype(k),                &
        obstime(k),wx(k)
    901       FORMAT(1X,a5,f6.2,1X,f7.2,1X,f5.0,1X,a8,1X,i4,1X,a8)
!wdt tmp
!    WRITE(*,1901) stn(k),lat(k),lon(k),elev(k),obstype(k),                &
!        obstime(k),wx(k)
!    1901       FORMAT("XXX stn dta:",1X,a5,f6.2,1X,f7.2,1X,f5.0,1X,a8,1X,i4,1X,a8)
!
    READ(1,903) t(k),td(k),dd(k),ff(k),ddg(k),ffg(k),pstn(k),           &
                pmsl(k),alt(k)
    903       FORMAT(4X,2(f6.1,1X),4(f5.0,1X),3(f6.1,1X))
!wdt tmp
!    WRITE(*,1903) t(k),td(k),dd(k),ff(k),ddg(k),ffg(k),pstn(k),           &
!                pmsl(k),alt(k)
!    1903       FORMAT("XXX         ",4X,2(f6.1,1X),4(f5.0,1X),3(f6.1,1X))
!
    READ(1,905) kloud(k),ceil(k),lowcld(k),cover(k),vis(k),rad(k),      &
        idp3(k)
    905       FORMAT(4X,i2,2(1X,f7.1),1X,f5.1,1X,f7.3,1X,f6.1,1X,i4)
!wdt tmp
!    WRITE(*,1905) kloud(k),ceil(k),lowcld(k),cover(k),vis(k),rad(k),      &
!        idp3(k)
!    1905       FORMAT("XXX cloud   ",4X,i2,2(1X,f7.1),1X,f5.1,1X,f7.3,1X,f6.1,1X,i4)
!
!.....  Read the cloud data if we have any.
!
    DO ii=1,5
      store_emv(k,ii) = ' '
      store_amt(k,ii) = '    '
      store_hgt(k,ii) = badflag
    END DO ! ii
    IF(kloud(k) > 0) THEN
!wdt update
      DO ii=1,kloud(k)
        IF (ii <= 5) THEN
          READ(1,907) store_emv(k,ii),store_amt(k,ii),store_hgt(k,ii)
          907           FORMAT(5X,a1,1X,a4,1X,f7.1)
!wdt tmp
!        WRITE(*,1907) store_emv(k,ii),store_amt(k,ii),store_hgt(k,ii)
!        1907           FORMAT("XXX storm   ",5X,a1,1X,a4,1X,f7.1)
        ELSE
          READ (1)
          WRITE (*,*) "SKIPPING extra cloud layers for station ",stn(k)
        END IF
      END DO !ii
    END IF
!
  END DO !k
!
  REWIND(1)
  CLOSE(1)
!
  CALL blklistsfc(blackfile,maxsta,istart,n_obs_b,misval,badflag,       &
      stn,obstype,wx,                                                   &
      t,td,dd,ff,ddg,ffg,pstn,pmsl,alt,kloud,ceil,lowcld,cover,rad,     &
      idp3,store_emv,store_amt,store_hgt,vis,istatus)
!
!..... End of data gathering. Let's go home...
!
  istatus = 1             ! everything's ok...
  PRINT *, ' Normal completion of READ_SURFACE_OBS'
!
  RETURN
!
!
  ENTRY read_surface_header(infile,atime,n_meso_g,n_meso_pos,           &
      n_sao_g,n_sao_pos_g,n_sao_b,n_sao_pos_b,n_obs_g,n_obs_pos_g,      &
      n_obs_b,n_obs_pos_b,istatus)
!
!.....  Entry to read and pass back just the header info from the lso file.
!
!.....  Open the file.  Check for a 'file not found' or other problem.
!
  istatus = 0
  OPEN(1,IOSTAT=ios,FILE=trim(infile),STATUS='old',                     &
       ACCESS='sequential',FORM='formatted')
  IF(ios /= 0) THEN     ! error during read
    istatus = -1
    WRITE(6,650) infile
    WRITE(6,651) ios
    RETURN
  END IF
!
!.....  File open...first read the header.
!
  READ(1,900) atime,              & ! data time
           n_meso_g,          & ! # of mesonet stations
           n_meso_pos,        & ! total # mesonet stations possible
           n_sao_g,           & ! # of saos in the laps grid
           n_sao_pos_g,       & ! total # of saos possible in laps grid
           n_sao_b,           & ! # of saos in the box
           n_sao_pos_b,       & ! total # of saos possible in the box
           n_obs_g,           & ! # of obs in the laps grid
           n_obs_pos_g,       & ! total # of obs psbl in the laps grid
           n_obs_b,           & ! # of obs in the box
           n_obs_pos_b        ! total # of obs possible in the box
!
!.....  Rewind and close the file so we can call this again in the same program.
!
  REWIND(1)
  CLOSE(1)
  istatus = 1
!
  RETURN
END SUBROUTINE read_surface_obs
!


SUBROUTINE blklistsfc(blkfile,maxsta,istart,nobs,misval,rmisval,        & 2,1
           stn,obstype,wx,                                              &
           t,td,dd,ff,ddg,ffg,pstn,pmsl,alt,kloud,ceil,lowcld,cover,rad, &
           idp3,store_emv,store_amt,store_hgt,vis,istatus)
!
!  Reads list of stations and variables from a file
!  to force variables known to be chronically wrong to "missing".
!
!  Keith Brewster, CAPS
!  May, 1995
!
  IMPLICIT NONE
!
!  Arguments
!
  CHARACTER (LEN=132) :: blkfile
  INTEGER :: maxsta,istart,nobs,misval
  REAL :: rmisval
  CHARACTER (LEN=5) :: stn(maxsta)
  REAL :: t(maxsta),td(maxsta)
  REAL :: dd(maxsta),ff(maxsta),ddg(maxsta),ffg(maxsta)
  REAL :: pstn(maxsta),pmsl(maxsta),alt(maxsta)
  REAL :: store_hgt(maxsta,5)
  REAL :: ceil(maxsta),lowcld(maxsta),cover(maxsta)
  REAL :: vis(maxsta),rad(maxsta)
!
  INTEGER :: kloud(maxsta),idp3(maxsta)
!
  CHARACTER (LEN=8) :: wx(maxsta)
  CHARACTER (LEN=8) :: obstype(maxsta)
  CHARACTER (LEN=1) :: store_emv(maxsta,5)
  CHARACTER (LEN=4) :: store_amt(maxsta,5)
  INTEGER :: istatus,iostatus
!
!  Some internal parameters
!
  INTEGER :: maxblk
  PARAMETER (maxblk=10)
  CHARACTER (LEN=40) :: BLANK
  PARAMETER(BLANK='                                        ')
!
!  Misc internal variables
!
  CHARACTER (LEN=5) :: blkstn
  INTEGER :: blkvar(maxblk)
  INTEGER :: i,iunit,ista,ivar,nblack
  LOGICAL :: found
!
  CALL getunit(iunit)
  OPEN(iunit,FILE=trim(blkfile),STATUS='old')
  DO 
    READ(iunit,'(a5,i5)',IOSTAT=iostatus) blkstn,nblack
    IF(iostatus < 0 ) EXIT
    IF(iostatus > 0 ) THEN
      WRITE(6,'(a,a)') ' Error reading blacklist file ',          &
       trim(blkfile)
      EXIT
    END IF
    DO i=1,maxblk
      blkvar(i)=-99
    END DO
    READ(iunit,*) (blkvar(i),i=1,nblack)
    found=.false.
    DO i=1,nobs
      ista=i+istart-1
      IF(stn(ista) == blkstn) THEN
        found=.true.
        DO ivar=1,nblack
          SELECT CASE (blkvar(ivar))
          CASE(1)
            WRITE(6,'(a,i4,a,a)') ' Blacklisting Temperature',    &
              blkvar(ivar),' at ',blkstn
            t(ista)=rmisval
          CASE(2)
            WRITE(6,'(a,i4,a,a)') ' Blacklisting Dew Point',      &
              blkvar(ivar),' at ',blkstn
            td(ista)=rmisval
          CASE(3)
            WRITE(6,'(a,i4,a,a)') ' Blacklisting Wind Variables', &
              blkvar(ivar),' at ',blkstn
            dd(ista)=rmisval
            ff(ista)=rmisval
            ddg(ista)=rmisval
            ffg(ista)=rmisval
          CASE(4)
            WRITE(6,'(a,i4,a,a)') ' Blacklisting Press Variables',&
              blkvar(ivar),' at ',blkstn
            pstn(ista)=rmisval
            pmsl(ista)=rmisval
            alt(ista)=rmisval
          CASE(5)
            WRITE(6,'(a,i4,a,a)') ' Blacklisting Cloud variables',&
              blkvar(ivar),' at ',blkstn
            kloud(ista)=0
            ceil(ista)=rmisval
            lowcld(ista)=rmisval
            cover(ista)=rmisval
          CASE(6)
            WRITE(6,'(a,i4,a,a)') ' Blacklisting Visibility',     &
              blkvar(ivar),' at ',blkstn
            vis(ista)=rmisval
          CASE(7)
            WRITE(6,'(a,i4,a,a)') ' Blacklisting Solar Radiation',&
              blkvar(ivar),' at ',blkstn
            rad(ista)=rmisval
          CASE DEFAULT
            WRITE(6,'(a,i4,a,a)') ' Invalid variable number ',    &
              blkvar(ivar),' at ',blkstn
          END SELECT
        END DO
        CYCLE
      END IF
    END DO
    IF(.NOT. found) WRITE(6,'(a,a,a)')                       &
      ' Blacklisted station ',blkstn,' not found in dataset'
  END DO
  CLOSE (iunit)
  CALL retunit(iunit)
  RETURN
END SUBROUTINE blklistsfc