C$$$  SUBPROGRAM DOCUMENTATION BLOCK
C                .      .    .                                       .
C SUBPROGRAM:    MQCFLTR     FILTER OBS BASED ON QC DATA DESCRIPTORS
C   PRGMMR: M. BARTH         ORG: FSL        DATE: 99-09-28
C
C ABSTRACT: FILTER OBS BASED ON QC DATA DESCRIPTORS.  SEE REMARKS
C   SECTION FOR A DISCUSSION OF THE FILTERING.
C
C PROGRAM HISTORY LOG:
C   99-09-28  M. BARTH    ORIGINAL VERSION
C   00-03-24  M. BARTH    - QCTYPE = 99 OPTION
C                         - VCN ARGUMENT
C                         - "I" DESCRIPTOR (GOOD-INTERPOLATED)
C                         - "W" DESCRIPTOR (GOOD-CORRECTED)
C                         - RAOB_HT_QC, RAOB_WIND_QC LOGIC
C   01-05-04  M. BARTH    ADDED NLEVELS & LT AS ARGUMENTS
C   01-07-02  M. BARTH    - ADDED DSN ARGUMENT
C                         - CHANGED FUNCTIONALITY SO THAT NO QC
C                           FILTERING IS DONE ON VARIABLES THAT
C                           CANNOT BE EXPECTED TO HAVE ANY QC
C                         - ADDED "T" DESCRIPTOR (TREATED LIKE I/W)
C   03-09-25  M. BARTH    ADDED SPECIAL QC CASE FOR AWIPS DATABASE,
C                         SATWND HDW1H DATASET (FROM FSL, HAS QC).
C   04-10-18  L. BENJAMIN ADDED NO QC FLAG
C   07-13-11  L. BENJAMIN ADDED RSAS DOMAIN CHECK TO DETERMINE MAX QC
C                         FOR SFC DATA
C
C USAGE:    CALL MQCFLTR (VCN,DSN,N1,N2,QCDESC,NLEVELS,LT,OB)
C
C   INPUT ARGUMENT LIST:
C     VCN      - I       VARIABLE CODE NUMBER
C     DSN      - I       DATASET CODE NUMBER
C     N1       - I       COLUMN DIMENSION OF ARRAYS
C     N2       - I       ROW DIMENSION OF ARRAYS
C     QCDESC   - C       ARRAY OF QC DATA DESCRIPTORS
C     NLEVELS  - IA      ARRAY OF NLEVELS FOR EACH STATION
C     LT       - IA      ARRAY OF LEVEL TYPES FOR EACH STATION
C
C   OUTPUT ARGUMENT LIST:
C     OB       - RA      OB ARRAY:  MISSING VALUES FILLED IN WHERE
C                        FILTERING IS DONE
C
C SUBPROGRAMS CALLED:
C     UNIQUE:    MQCINQ
C
C REMARKS:
C   - FILTERING CHOICES ARE FOUND IN MADISCOM'S QCTYPE VARIABLE,
C     WHICH IS FILLED IN BY MSETQC.  THE DEFAULT VALUE, 0,
C     MEANS NO QC FILTERING WILL BE DONE.  OTHERWISE, ONLY VALUES
C     PASSING QC WILL BE RETURNED.  IN OTHER WORDS, IF THE USER
C     SELECTS COARSE QC FILTERING, AND WE HAVE AN OB THAT PASSED
C     THE STAGE 1 CHECKS BUT FAILED A HIGHER-ORDER CHECK, THE OB
C     WILL BE FILTERED.
C   - SUBJECTIVE QC OVERRIDES THE QC CHECKS.  THEREFORE, IF QC
C     FILTERING IS TURNED ON, SUBJECTIVE GOOD WILL ALWAYS BE
C     RETURNED AND SUBJECTIVE BAD WILL ALWAYS BE FILTERED.
C   - THE FQCINC FUNCTION CAN BE USED TO INQUIRE ABOUT THE HIGHEST
C     LEVEL OF QC POSSIBLY AVAILABLE FOR A GIVEN VARIABLE, AND THE
C     VALUE RETURNED BY THAT FUNCTION CAN BE USED AS INPUT TO THE
C     MSETQC ROUTINE.  ALTERNATIVELY, THE USER CAN SPECIFY THE HIGHEST
C     LEVEL POSSIBLE BE USED FOR EACH VARIABLE/DATASET BY SETTING
C     QCTYPE TO 99 IN MSETQC.
C   - NLEVELS & LT ARE ONLY USED FOR SOME DATASETS.  CURRENTLY
C     THIS SET INCLUDES:  RAOBS.
C   - DSN IS ONLY USED FOR SOME DATA TYPES.  CURRENTLY THIS SET 
C     INCLUDES:  SFC (MESONET), SATWND (HDW1H).
C   - THIS ROUTINE REQUIRES SPECIFIC, HARD-WIRED LOGIC CONCERNING
C     DATASETS/DATABASES THAT DO NOT HAVE QC INFO AVAILABLE (E.G.,
C     EVERYTHING EXCEPT MESONET IN THE AWIPS DATABASE).  WHENEVER THOSE
C     OPTIONS CHANGE, THIS ROUTINE WILL NEED TO BE CHANGED.
C
C ATTRIBUTES:
C   LANGUAGE: FORTRAN-77 + EXTENSIONS
C   MACHINE:  UNIX
C$$$

      SUBROUTINE MQCFLTR (VCN,DSN,N1,N2,QCDESC,NLEVELS,LT,OB)

C     ------------------------------------------------------------------
C     INCLUDES AND COMMONS
C     ------------------------------------------------------------------
      INCLUDE 'IMPLICIT'
      INCLUDE 'MADISCON'
      INCLUDE 'MADISCOM'
      INCLUDE 'MADISTMP'

C     ------------------------------------------------------------------
C     ARGUMENTS
C     ------------------------------------------------------------------
      INTEGER VCN,DSN,N1,N2,NLEVELS(*),LT(N1,N2)
      CHARACTER*1 QCDESC(N1,N2)
      REAL OB(N1,N2)

C     ------------------------------------------------------------------
C     LOCAL
C     ------------------------------------------------------------------
      INTEGER I,J,IQCTYPE,MAXQC
      INTEGER MQCINQ
      LOGICAL RAOB_QC,SFC_MAX_QC

      RAOB_QC = .FALSE.
      SFC_MAX_QC = .FALSE.


C     ------------------------------------------------------------------
C     DETERMINE THE HIGHEST POSSIBLE QC LEVEL FOR THE VARIABLE/DATASET.
C     THEN ADJUST THAT BASED ON HARD-WIRED LOGIC FOR WHAT DATABASES
C     AND DATASETS HAVE ANY QC AT ALL.  IF IT TURNS OUT THAT NO QC
C     IS AVAILABLE, RETURN WITHOUT DOING ANY FILTERING.
C     ------------------------------------------------------------------
      MAXQC = MQCINQ(VCN,I)
      IF(I.NE.SUCCESS_P)RETURN
      IF(CDBTYPE.EQ.AWIPS_DB_P.AND.
     1   (CDTYPE.EQ.SFC_DS_P.AND.(DSN.NE.MESONET_DS_P.OR.AWIPS2_DB)).OR.
     2   (CDTYPE.EQ.SATW_DS_P.AND.DSN.NE.HDW1H_DS_P))MAXQC = 0
      IF(MAXQC.EQ.0 .OR.
     1   (MAXQC.GT.0 .AND. QCSTATUS.EQ.EQCFAILED_P))RETURN

C     ------------------------------------------------------------------
C     IF QCTYPE IS 99, THEN USE THE HIGHEST POSSIBLE QC LEVEL
C     AVAILABLE FOR THIS VARIABLE/DATASET.
C     ------------------------------------------------------------------
      IF(QCTYPE.NE.99)THEN

         IQCTYPE = QCTYPE

      ELSE

         IQCTYPE = MAXQC
         IF(CDTYPE.EQ.RAOB_DS_P.AND.(RAOB_HT_QC.OR.RAOB_WIND_QC))
     1      RAOB_QC = .TRUE.

         IF(CDTYPE.EQ.SFC_DS_P)SFC_MAX_QC = .TRUE.

      ENDIF

C     ------------------------------------------------------------------
C     IF NO FILTERING WAS SELECTED, RETURN.  OTHERWISE, LOOP THROUGH
C     THE DATA AND KNOCK OUT OB VALUES WITH INSUFFICIENT QUALITY.
C     ------------------------------------------------------------------
      IF(IQCTYPE.EQ.0)THEN

         RETURN

      ELSE IF(RAOB_QC)THEN

C     ------------------------------------------------------------------
C     HERE'S THE RAOB QC WRINKLE:  MANDATORY LEVEL WINDS AND HEIGHTS
C     HAVE QC LEVEL 2 AS THE MAX LEVEL POSSIBLE, NON-MANDATORY WINDS
C     AND HEIGHTS ONLY HAVE LEVEL 1.  AS BOTH OF THESE CAN BE COMBINED
C     IN AN INTEGRATED SOUNDING (E.G., ONE CALL FOR ONE VCN), WE HAVE
C     TO SORT THIS OUT HERE.  ALSO NOTE THAT FOR HEIGHT OBS, "MANDATORY"
C     INCLUDES THE SURFACE LEVEL, BUT THAT'S NOT TRUE FOR WIND OBS...
C     ------------------------------------------------------------------
         DO 11 J = 1, N2

            DO 12 I = 1, NLEVELS(J)

               IF(RAOB_WIND_QC.AND.LT(I,J).NE.MAN_RAOB_P.AND.
     1            QCDESC(I,J).NE.'C'.AND.QCDESC(I,J).NE.'S'.AND.
     2            QCDESC(I,J).NE.'V'.AND.QCDESC(I,J).NE.'G'.AND.
     3            QCDESC(I,J).NE.'I'.AND.QCDESC(I,J).NE.'W'.AND.
     4            QCDESC(I,J).NE.'T')THEN

                  OB(I,J) = MISS_P

               ELSE IF(RAOB_WIND_QC.AND.LT(I,J).EQ.MAN_RAOB_P.AND.
     1                 QCDESC(I,J).NE.'S'.AND.QCDESC(I,J).NE.'V'.AND.
     2                 QCDESC(I,J).NE.'G'.AND.QCDESC(I,J).NE.'I'.AND.
     3                 QCDESC(I,J).NE.'W'.AND.QCDESC(I,J).NE.'T')THEN

                  OB(I,J) = MISS_P

               ELSE IF(RAOB_HT_QC.AND.LT(I,J).NE.MAN_RAOB_P.AND.
     1                 LT(I,J).NE.SFC_RAOB_P.AND.
     2                 QCDESC(I,J).NE.'C'.AND.QCDESC(I,J).NE.'S'.AND.
     3                 QCDESC(I,J).NE.'V'.AND.QCDESC(I,J).NE.'G'.AND.
     4                 QCDESC(I,J).NE.'I'.AND.QCDESC(I,J).NE.'W'.AND.
     5                 QCDESC(I,J).NE.'T')THEN

                  OB(I,J) = MISS_P

               ELSE IF(RAOB_HT_QC.AND.(LT(I,J).EQ.MAN_RAOB_P.OR.
     1                 LT(I,J).EQ.SFC_RAOB_P).AND.
     2                 QCDESC(I,J).NE.'S'.AND.QCDESC(I,J).NE.'T'.AND.
     3                 QCDESC(I,J).NE.'V'.AND.QCDESC(I,J).NE.'G'.AND.
     4                 QCDESC(I,J).NE.'I'.AND.QCDESC(I,J).NE.'W')THEN

                  OB(I,J) = MISS_P

               ENDIF

 12         CONTINUE

 11      CONTINUE

      ELSE IF(IQCTYPE.EQ.1)THEN

         DO 1 J = 1, N2

            DO 2 I = 1, N1

               IF(QCDESC(I,J).NE.'C'.AND.QCDESC(I,J).NE.'S'.AND.
     1            QCDESC(I,J).NE.'V'.AND.QCDESC(I,J).NE.'G'.AND.
     2            QCDESC(I,J).NE.'I'.AND.QCDESC(I,J).NE.'W'.AND.
     3            QCDESC(I,J).NE.'T')OB(I,J) = MISS_P

 2             CONTINUE

 1          CONTINUE

      ELSE IF(IQCTYPE.EQ.2)THEN

         DO 31 J = 1, N2

            DO 32 I = 1, N1

               IF(QCDESC(I,J).NE.'S'.AND.QCDESC(I,J).NE.'I'.AND.
     1            QCDESC(I,J).NE.'V'.AND.QCDESC(I,J).NE.'G'.AND.
     2            QCDESC(I,J).NE.'W'.AND.QCDESC(I,J).NE.'T')
     4              OB(I,J) = MISS_P

 32         CONTINUE

 31      CONTINUE

C     ------------------------------------------------------------------
C     HERE'S THE SFC QC WRINKLE:  RSAS DOMAIN SITES HAVE QC LEVEL 3 
C     WHILE NON-RSAS DOMAIN SITES MAX QC IS LEVEL 2.  USE THE SITES
C     COMMIN TO SORT THIS OUT.
C     ------------------------------------------------------------------

      ELSE IF(IQCTYPE.EQ.3 .AND. SFC_MAX_QC)THEN

         DO 23 J = 1, N2

            IF(INRSASDMN(J))THEN
               DO 24 I = 1, N1

                  IF(QCDESC(I,J).NE.'V'.AND.QCDESC(I,J).NE.'G'.AND.
     1                 QCDESC(I,J).NE.'I'.AND.QCDESC(I,J).NE.'W'.AND.
     2                 QCDESC(I,J).NE.'T')OB(I,J) = MISS_P
 24            CONTINUE
            ELSE
               DO 34 I = 1, N1

                  IF(QCDESC(I,J).NE.'S'.AND.QCDESC(I,J).NE.'V'.AND.
     1                 QCDESC(I,J).NE.'G'.AND.QCDESC(I,J).NE.'I'.AND.
     2                 QCDESC(I,J).NE.'W'.AND.QCDESC(I,J).NE.'T')
     3                 OB(I,J) = MISS_P                  
 34            CONTINUE
                  
            ENDIF

 23      CONTINUE

      ELSE IF(IQCTYPE.EQ.3)THEN

         DO 21 J = 1, N2

            DO 22 I = 1, N1

               IF(QCDESC(I,J).NE.'V'.AND.QCDESC(I,J).NE.'G'.AND.
     1            QCDESC(I,J).NE.'I'.AND.QCDESC(I,J).NE.'W'.AND.
     2            QCDESC(I,J).NE.'T')OB(I,J) = MISS_P

 22         CONTINUE

 21      CONTINUE

      ENDIF

      RETURN
      END
C**---------------------------------------------------------------------
C**REQUIRED STANDARD FSL DISCLAIMER (NOVEMBER 2000)
C**---------------------------------------------------------------------
C**  OPEN SOURCE LICENSE/DISCLAIMER,  FORECAST SYSTEMS LABORATORY
C**  NOAA/OAR/FSL, 325 BROADWAY BOULDER, CO 80305
C**
C**  THIS SOFTWARE IS DISTRIBUTED UNDER THE OPEN SOURCE DEFINITION, 
C**  WHICH MAY BE FOUND AT http://www.opensource.org/osd.html.
C**
C**  IN PARTICULAR, REDISTRIBUTION AND USE IN SOURCE AND BINARY FORMS,
C**  WITH OR WITHOUT MODIFICATION, ARE PERMITTED PROVIDED THAT THE 
C**  FOLLOWING CONDITIONS ARE MET:
C**
C**  - REDISTRIBUTIONS OF SOURCE CODE MUST RETAIN THIS NOTICE, THIS LIST
C**    OF CONDITIONS AND THE FOLLOWING DISCLAIMER.
C**
C**  - REDISTRIBUTIONS IN BINARY FORM MUST PROVIDE ACCESS TO THIS 
C**    NOTICE, THIS LIST OF CONDITIONS AND THE FOLLOWING DISCLAIMER, AND
C**    THE UNDERLYING SOURCE CODE.
C**
C**  - ALL MODIFICATIONS TO THIS SOFTWARE MUST BE CLEARLY DOCUMENTED, 
C**    AND ARE SOLELY THE RESPONSIBILITY OF THE AGENT MAKING THE 
C**    MODIFICATIONS.
C**
C**  - IF SIGNIFICANT MODIFICATIONS OR ENHANCEMENTS ARE MADE TO THIS
C**    SOFTWARE, THE FSL SOFTWARE POLICY MANAGER 
C**    (softwaremgr.fsl@noaa.gov) BE NOTIFIED.
C**
C**  THIS SOFTWARE AND ITS DOCUMENTATION ARE IN THE PUBLIC DOMAIN AND 
C**  ARE FURNISHED "AS IS."  THE AUTHORS, THE UNITED STATES GOVERNMENT,
C**  ITS INSTRUMENTALITIES, OFFICERS, EMPLOYEES, AND AGENTS MAKE NO 
C**  WARRANTY, EXPRESS OR IMPLIED, AS TO THE USEFULNESS OF THE SOFTWARE
C**  AND DOCUMENTATION FOR ANY PURPOSE.  THEY ASSUME NO RESPONSIBILITY 
C**  (1) FOR THE USE OF THE SOFTWARE AND DOCUMENTATION; OR (2) TO 
C**  PROVIDE TECHNICAL SUPPORT TO USERS.
C**---------------------------------------------------------------------
