SUBROUTINE Aerosol_Detect (&
&    K__SENSOR,     &
&    K__NCHANS,     &
&    K__CHANID,     &
&    P__MODELBTs,   &    
&    P__OBSBTs,     &
&    LD__AerosolPresent)

!**** Aerosol Detection
!        A. Collard  ECMWF 17/05/06   

!     PURPOSE
!     -------
!        Look for aerosol signal in AIRS/IASI radiances

!**   INTERFACE
!     ---------
!        aerosol_detect is called from cloud_detect

!     METHOD
!     ------
!        A unique theoretically derived aerosol signal is sought through
!        linear regression of firt guess departures.

!     EXTERNALS
!     ---------

!     MODIFICATIONS
!     -------------
!     17/05/06  Original code.     A. Collard

USE PARKIND1,ONLY : JPIM     ,JPRB
USE YOMHOOK, ONLY : LHOOK,   DR_HOOK
USE YOMIASI, ONLY : S__Cloud_Detect_Setup
USE YOMLUN,  ONLY : NULOUT   

IMPLICIT NONE

! Subroutine arguments

INTEGER(KIND=JPIM),INTENT(IN)    :: K__SENSOR ! sensor
INTEGER(KIND=JPIM),INTENT(IN)    :: K__NCHANS ! no. of channels 
INTEGER(KIND=JPIM),INTENT(IN)    :: K__CHANID(K__NCHANS)  ! Channel IDs
REAL(KIND=JPRB)   ,INTENT(IN)    :: P__MODELBTS(K__NCHANS)! Model clear 
                                                          ! radiance estimates
REAL(KIND=JPRB)   ,INTENT(IN)    :: P__OBSBTS(K__NCHANS)  ! Observed radiances
LOGICAL           ,INTENT(OUT)   :: LD__AerosolPresent

! Local variables

INTEGER(KIND=JPIM)           :: J, I__K, I__Test
INTEGER(KIND=JPIM)           :: I__MaxChans
INTEGER(KIND=JPIM)           :: I__Num_Aerosol_Chans
INTEGER(KIND=JPIM)           :: I__NumFoundChans

INTEGER(KIND=JPIM), POINTER  :: I__Aerosol_Chans(:)

REAL(KIND=JPRB),POINTER      :: Z__Aerosol_Abscissae(:)
REAL(KIND=JPRB)              :: Z__Aerosol_Threshold
REAL(KIND=JPRB)              :: Z__AerosolMinNorm

REAL(KIND=JPRB), ALLOCATABLE :: Z__X(:), Z__Y(:)
REAL(KIND=JPRB)              :: Z__SumX, Z__SumY, Z__SumXX, Z__SumXY, Z__Det
REAL(KIND=JPRB)              :: Z__Gradient
REAL(KIND=JPRB)              :: Z__Norm

REAL(KIND=JPRB) :: ZHOOK_HANDLE

!-----------------------------------
! Initialise
!-----------------------------------

IF (LHOOK) CALL DR_HOOK('AEROSOL_DETECT',0,ZHOOK_HANDLE)

LD__AerosolPresent = .FALSE.

I__MaxChans = &
&      MAXVAL(S__Cloud_Detect_Setup(K__SENSOR) % N__Num_Aerosol_Chans(:))
ALLOCATE(Z__X(I__MaxChans))
ALLOCATE(Z__Y(I__MaxChans))

!-----------------------------------
! Loop through tests
!-----------------------------------

TestLoop : DO I__Test = &
&                1, S__Cloud_Detect_Setup(K__SENSOR) % N__Num_Aerosol_Tests

   I__Num_Aerosol_Chans = &
&        S__Cloud_Detect_Setup(K__SENSOR) % N__Num_Aerosol_Chans(I__Test)
   I__Aerosol_Chans => S__Cloud_Detect_Setup(K__SENSOR) % &
&        N__Aerosol_Chans(1:I__Num_Aerosol_Chans,I__Test)
   Z__Aerosol_Abscissae => S__Cloud_Detect_Setup(K__SENSOR) % &
&        R__Aerosol_Abscissae(1:I__Num_Aerosol_Chans,I__Test)
   Z__Aerosol_Threshold = &
&        S__Cloud_Detect_Setup(K__SENSOR) % R__Aerosol_Threshold(I__Test)
   Z__AerosolMinNorm = &
&        S__Cloud_Detect_Setup(K__SENSOR) % R__AerosolMinNorm(I__Test)

   ! Get appropriate first guess departures.
   I__NumFoundChans = 0
   DO J=1,I__Num_Aerosol_Chans
      DO I__K=1,K__NCHANS
         IF (K__CHANID(I__K) == I__Aerosol_Chans(J)) THEN
            IF (P__OBSBTS(I__K) < 0. .OR. P__MODELBTS(I__K) < 0.) CYCLE
            I__NumFoundChans = I__NumFoundChans + 1
            Z__Y(I__NumFoundChans) = P__OBSBTS(I__K)-P__MODELBTS(I__K)
            Z__X(I__NumFoundChans) = Z__Aerosol_Abscissae(J)
         ENDIF
      ENDDO
      IF ( I__NumFoundChans == 0 ) THEN
         WRITE(NULOUT,*) &
&          '**AEROSOL_DETECT - WARNING: CHANNELS NOT FOUND CYCLING TEST: **', &
              &          I__Test
         CYCLE TestLoop
      ENDIF
   ENDDO

   ! Normalise and do least squares fit to get gradient

   Z__Norm = MAX(SUM(ABS(Z__Y(1:I__NumFoundChans)))/I__NumFoundChans, &
&                  Z__AerosolMinNorm)
   Z__Y(:) = Z__Y(:)/Z__Norm 
   Z__SumX = SUM(Z__X(1:I__NumFoundChans))
   Z__SumY = SUM(Z__Y(1:I__NumFoundChans))
   Z__SumXX = SUM(Z__X(1:I__NumFoundChans)*Z__X(1:I__NumFoundChans))
   Z__SumXY = SUM(Z__X(1:I__NumFoundChans)*Z__Y(1:I__NumFoundChans))
   Z__Det   = I__NumFoundChans*Z__SumXX - (Z__SumX)**2
   ! Gradient is -ve as we are looking for -ve FG departures
   Z__Gradient = -(I__NumFoundChans*Z__SumXY - Z__SumX*Z__SumY)/Z__Det

   ! Compare to pre-determined threshold
   IF (Z__Gradient > Z__Aerosol_Threshold) THEN 
      LD__AerosolPresent = .TRUE.
      EXIT TestLoop
   ENDIF

ENDDO TestLoop

DEALLOCATE(Z__X)
DEALLOCATE(Z__Y)
NULLIFY(I__Aerosol_Chans)
NULLIFY(Z__Aerosol_Abscissae)

IF (LHOOK) CALL DR_HOOK('AEROSOL_DETECT',1,ZHOOK_HANDLE)

END SUBROUTINE Aerosol_Detect
