
      SUBROUTINE calcml(phamod, phaobs, phacor, phabkg, region, brgion,
     &                  areasc, breasc, likely)

      IMPLICIT NONE

      REAL phamod(*), phaobs(*), phacor(*), phabkg(*)
      REAL region(*), brgion(*), areasc(*), breasc(*)
      REAL likely

c      calcml      kaa 9 January 1989
c            XSPEC subroutine to calculate likelihood for a particular
c            measurement array
c!!  try and put in ML formula from Cash - this only works if
c    errors are only counting statistics on source
c    The pathological case of model(E)=0 is handled by setting
c    log(model(E))=-32.

c  6/23/95 use normalization suggested by John Castor to give a
c          goodness-of-fit

c      phamod      r            i: model values
c      phaobs      r            i: observed count rate
c      phacor      r            i: correction on observed count rate
c      phabkg      r            i: background count rate
c      region      r            i: source BACKSCAL values
c      brgion      r            i: background BACKSCAL values
c      areasc      r            i: source AREASCAL values
c      breasc      r            i: background AREASCAL values
c      likely      r            r: value of likelihood


      DOUBLE PRECISION dconv, dsum, dobs, dmod, ldobs, ldmod
      DOUBLE PRECISION dbconv, dbobs, dtconv, dbfact, dfact
      INTEGER ipha, idset
      CHARACTER wrtstr*255
      LOGICAL qwarn

      DOUBLE PRECISION lprior, wcntrb
      REAL dgtime, dgbtme
      INTEGER dgndst, dgnbnb, dgnbne
      LOGICAL fgqcrf
      EXTERNAL dgndst, dgnbnb, dgnbne, dgtime, dgbtme
      EXTERNAL fgqcrf, lprior, wcntrb

      dsum = 0.d0

      DO idset = 1, dgndst()

         IF ( fgqcrf(idset) ) THEN
            WRITE(wrtstr,'(a,i4)') 
     &        'Correction data being ignored for dataset ', idset
            CALL xwrite(wrtstr, 10)
         ENDIF

c Check whether any of the source datapoints are negative - if so we should
c not be running cstat so warn the user

         qwarn = .FALSE.
         DO ipha = dgnbnb(idset), dgnbne(idset)
            IF ( phaobs(ipha) .LT. 0. ) qwarn = .TRUE.
         ENDDO
         IF ( qwarn ) THEN
            WRITE(wrtstr,'(a,i4,a,a)') 
     &        'Dataset ', idset, ' has bins with negative counts - ',
     &        'cstat will not work correctly'
            CALL xwrite(wrtstr, 10)
         ENDIF

         dfact = DBLE(dgtime(idset))

c First calculate the case of no background

         IF ( dgbtme(idset) .EQ. 0. ) THEN

            DO ipha = dgnbnb(idset), dgnbne(idset)

               dconv = dfact * DBLE(areasc(ipha))

               IF (phaobs(ipha) .LE. 0. ) THEN

                  dsum = dsum + dconv*DBLE(phamod(ipha))

               ELSE

                  dobs = dconv * DBLE(phaobs(ipha))
                  ldobs = log(dobs)

c Put a floor under the model of 1.e-5 counts/bin - should be well below
c the systematics limit

                  dmod = MAX(dconv * DBLE(phamod(ipha)), 1.d-5)
                  ldmod = log(dmod)

                  dsum = dsum + dmod - dobs + dobs*(ldobs-ldmod)

               ENDIF

            ENDDO

c Now if there is a background file defined

         ELSE

c Check for negative bins in the background file

            qwarn = .FALSE.
            DO ipha = dgnbnb(idset), dgnbne(idset)
               IF ( phabkg(ipha) .LT. 0. ) qwarn = .TRUE.
            ENDDO
            IF ( qwarn ) THEN
               WRITE(wrtstr,'(a,i4,a,a)') 
     &           'Dataset ', idset, ' has background bins with ',
     &           'negative counts - cstat will not work correctly'
               CALL xwrite(wrtstr, 10)
            ENDIF

            dbfact = DBLE(dgbtme(idset))

c Loop round channels in this dataset

            DO ipha = dgnbnb(idset), dgnbne(idset)

               dconv  = dfact*DBLE(areasc(ipha))
               dbconv = dbfact*DBLE(breasc(ipha))
     &                        *DBLE(brgion(ipha))/DBLE(region(ipha))
               dtconv = dconv + dbconv

               dobs = dconv*DBLE(phaobs(ipha))
               dmod = DBLE(phamod(ipha))
               dbobs = dbconv*DBLE(phabkg(ipha))

               dsum = dsum + wcntrb(dobs, dbobs, dmod, dconv, 
     &                              dbconv, dtconv)

c end loop over channels

            ENDDO

         ENDIF

c end loop over datasets

      ENDDO

c Include the Bayesian prior term (the log of the prior probability)

      likely = 2 * SNGL(dsum) - 2 * lprior()

      RETURN
      END

c ****************************************************************************

      FUNCTION wcntrb(dobs, dbobs, dmod, dconv, dbconv, dtconv)

      DOUBLE PRECISION wcntrb, dobs, dbobs, dmod, dconv, dbconv, dtconv

c Routine to calculate the contribution to W/2 from a given channel

      DOUBLE PRECISION da, db, dc, dq, df

c Handle the special cases - first if the source and background are zero

      IF ( dobs .EQ. 0 .AND. dbobs .EQ. 0 ) THEN

         wcntrb = dconv*dmod

c if source is non-zero but background is zero

      ELSEIF ( dobs .NE. 0 .AND. dbobs .EQ. 0 ) THEN

         IF ( dmod .LE. dobs/dtconv ) THEN

            wcntrb = - dmod*dbconv - dobs*log(dconv/dtconv)

         ELSE

            wcntrb = dmod*dconv - dobs*log(dmod*dconv)
     &                            - dobs*(1-log(dobs))

         ENDIF

c if source is zero and background is non-zero

      ELSEIF ( dobs .EQ. 0 .AND. dbobs .NE. 0 ) THEN

         wcntrb = dmod*dconv - dbobs*log(dbconv/dtconv)

c if the model is zero but the source and background are non-zero

      ELSEIF ( dmod .EQ. 0 .AND. dobs .NE. 0 .AND. dbobs .NE. 0 ) THEN

         wcntrb = dobs*log(dobs) + dbobs*log(dbobs) 
     &            - dobs*log(dconv*(dobs+dbobs)/dtconv)
     &            - dbobs*log(dbconv*(dobs+dbobs)/dtconv)

c now the standard solution with source, background, and model non-zero

      ELSE

c method from Numerical Recipes for solving a quadratic to avoid round-off
c error in the case when b^2 >> ac.

         da = dtconv
         db = dtconv*dmod - dobs - dbobs
         dc = -dbobs*dmod
         dq = -0.5*(db + SIGN(1.0d0,db)*SQRT( db*db - 4*da*dc ))
         df = dq/dtconv
         IF ( df .LT. 0.d0 ) df = dc/dq

         wcntrb = dconv*dmod + dtconv*df - dobs*(1-log(dobs)) 
     &                       - dbobs*(1-log(dbobs))

         IF ( (dconv*dmod+dconv*df) .GT. 0.d0 ) THEN
            wcntrb = wcntrb - dobs * log(dconv*dmod+dconv*df)
         ELSE
            wcntrb = wcntrb - dobs * (-32)
         ENDIF

         IF ( (dbconv*df) .GT. 0.d0 ) THEN
            wcntrb = wcntrb - dbobs * log(dbconv*df)
         ELSE
            wcntrb = wcntrb - dbobs * (-32)
         ENDIF

      ENDIF

      END







