[KLOE] [Offline Doc] [TRK Files]

Track Reconstruction Library

argtrk.kloe


C*HE 03/22/95 17:52:39
C*DK DFMAIN
C**********************************************************************
C   The track fit package of ARGUS collaboration
C   Written primarily by Hartwig Albrecht in 1982 and then updated by
C   him and R.Kutschke, H.Kapitza, Ubi, Roland Waldi
C   The description of the algorithm can be found in NIM A275, p.1-48.
C   and in unpublished and unfinished version of H.Kapitza's note
C   (at LNF vax cluster d19:[alex.argus.write-up]).
C   Formulas from NIM paper and Kapitza note are referenced in the code.
C   The original ARGUS code has been obtained from H.Kapitza
C-----------------------------------------------------------------------
C                  KLOE history
C                  ------------
C   Adopted for KLOE by A.Andryakov in 1992
C   Updated - 24.11.94 by A.Andryakov
C   Updated - 16.02.95 by G.Capon (style changes)
C   Updated - 17.03.95 by A.Andryakov (cleaned include file)
C                                     effects all parts p.r. + t.f. + v.f
C   Updated -  3.04.95 by G.Capon (ARGUS dynamical track candidates
C                           structure is replaced with YBOS bank structure)
C                      by A.Antonelli & A.Calcaterra (new DFSTOR to switch
C                           to YBOS banks)
C***********************************************************************
C
C=======================================================================
      SUBROUTINE DFMAIN
C=======================================================================
$$IMPLICIT
C
C --- MAIN ROUTINE FOR TRACK FITTING
C-----------------------------------------------------------------------
C
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$INC:OFERCO.INC'
C
$$INCLUDE 'C$INC:JOBSTA.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$ITRK:DTFS.INC'
$$INCLUDE 'K$ITRK:DCHD.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'         
$$INCLUDE 'K$ITRK:STUMPCOM.INC'        
$$INCLUDE 'K$ITRK:CFLAGS.INC'  



      INTEGER SUPERSTATUS,DPVER,IHIT
      INTEGER BLOCAT,BCOPYG,BNEXT,BDATA,BNUMB
      INTEGER STATUS,STATUS_DPRS,STATUS_DTFS

      INTEGER NPASS,I
      INTEGER IND,INDAT,IND_DPRS,INDAT_DPRS,IND_DTFS,INDAT_DTFS
      INTEGER INDR,INDDATR,DHRENCO,NDCHITS
      INTEGER PTRCAN,LOOP
      REAL    ALONE,PRHITS,FTHITS,CHINOR,PCHI2

      NPASS = 1

C  Before starting the fit 
C  create the second (running) version of banks DTCE and DHRE

      STATUS = BCOPYG(IW,'DTCE',1,'DTCE',2,IND,INDAT)
      STATUS = BCOPYG(IW,'DHRE',1,'DHRE',2,IND,INDAT)

C  Now locate the drift chamber header bank

      STATUS = BLOCAT(IW,'DCHD',1,IND,INDAT)
      IF (STATUS.EQ.YESUCC) THEN
        IND = INDAT + IW(INDAT+DCHHDS)
        IW(IND+DCHTRK) = 0
        IW(IND+DCHTCN) = 0
      ELSE
        CALL ERLOGR('DFMAIN',ERWARN,0,STATUS,
     +              'DC Header Bank not found!')
        RETURN
      ENDIF
C      WRITE(6,*)'Event nb :',NEV

C  Loop over p.r. track candidates

 20	continue 

      STATUS_DPRS = BLOCAT(IW,'DPRS',-1,IND_DPRS,INDAT_DPRS)
      DO WHILE (IND_DPRS.GT.0)

        IF (ldfjoi.GE.0) THEN
	   DPVER=IW(INDAT_DPRS+DPRVRN)
           IF(NPASS.eq.1) THEN
              if((DPVER.lt.10).and.DPVER.ne.NPASS) goto 100
           ELSE
              if(DPVER.ne.NPASS) goto 100
           ENDIF
	ENDIF

        JDPRS = INDAT_DPRS + IW(INDAT_DPRS+DPRHDS)

*******************************************
        IF (IW(JDPRS+DPRPOK) .EQ. 3) THEN
*******************************************

          JDPRS1 = JDPRS + DPRCEN
          STATUS = BNUMB(IW,IND_DPRS,ITR)
          PRHITS = IW(JDPRS+DPRPOS)+IW(JDPRS+DPRNEG)
          CALL HFILL(1,PRHITS,0.,1.)
          CALL VZERO(NDF,MXHIT)
          CALL DFFIT (NPASS)

        IF (ldfjoi.GE.0) THEN
	  do IHIT=1,MXHIT
	    KDFS(ITR,IHIT)=KDF(IHIT)	
	    DFSS(ITR,IHIT)=DFS(IHIT)	
	  enddo

          if(NPASS.eq.2) then    
	    call DTFSKILL(ITR)
          endif 	
	ENDIF


C  If the track fit succeeded, then the following bank must exist

          STATUS_DTFS = BLOCAT(IW,'DTFS',ITR,IND_DTFS,INDAT_DTFS)
          IND_DTFS = INDAT_DTFS + IW(INDAT_DTFS+DTFHDS)
          IF (STATUS_DTFS.EQ.YESUCC) THEN
            IW(IND+DCHTRK) = IW(IND+DCHTRK)+1
            IF (IW(IND_DTFS+DTFCEN).EQ.1) THEN
              IW(IND+DCHTCN) = IW(IND+DCHTCN)+1
            ENDIF
            FTHITS = NFITPOS+NFITNEG
            CALL HFILL(4,FTHITS,0.,1.)
            CHINOR=RW(IND_DTFS+DTFCHI)/(FTHITS-5)
            CALL HFILL(9,CHINOR,0.,1.)
            PCHI2 = RW(IND_DTFS+DTFPCH)
            CALL HFILL(10,PCHI2,0.,1.)
          ELSE

C  If not, then the track fit failed. Histogram the number of hits for
C  the candidate, and the last track fit error code

            CALL HFILL(11,PRHITS,0.,1.) 
            CALL HFILL(12,FLOAT(NDFERR),0.,1.)
          ENDIF

******************************************
        ENDIF
******************************************

 100    continue 
        STATUS_DPRS=BNEXT(IW,IND_DPRS,IND_DPRS)
        STATUS_DTFS=BDATA(IW,IND_DPRS,INDAT_DPRS)
      ENDDO

C  At the end of the first step of track-fitting do some control histograms

      CALL HFILL(5,FLOAT(IW(IND+DCHTRK)),0.,1.)
      CALL HFILL(6,FLOAT(IW(IND+DCHTCN)),0.,1.)

      STATUS = BLOCAT(IW,'DHRE',2,INDR,INDDATR)
      IF (STATUS .NE. YESUCC) RETURN
      INDR = INDDATR+IW(INDDATR+DHRHDS)
      DHRENCO = IW(INDDATR+DHRNCO)
      NDCHITS = IW(INDDATR+DHRNRO)
      ALONE = 0.
      PTRCAN = INDR+DHRTRN
      DO LOOP=1,NDCHITS
        IF (IW(PTRCAN).LE.0) ALONE = ALONE+1.
        PTRCAN = PTRCAN+DHRENCO
      ENDDO
      CALL HFILL(7,ALONE,0.,1.)
      CALL HFILL(8,ALONE/FLOAT(NDCHITS),0.,1.)
C
C  Decides if a track is to be splitted in two
      IF(KINK_RECO.and.(NPASS.eq.1)) THEN
         CALL DFSPLIT
      ENDIF
C
C
C  Identify and join track stumps

      IF (ldfjoi.GE.0) THEN
         if(NPASS.eq.2) then
	   goto 900  !<COM6-11 for the moment only one join trk at time
         endif	
         CALL DFJOIN(SUPERSTATUS)  
         if(SUPERSTATUS.eq.OFSUCC) then
	   NPASS = NPASS+1 
	   goto 20
         endif	
      ENDIF

 900  RETURN
      END
C
C*DK DFADD
C
C=======================================================================
C
      SUBROUTINE DFADD (NADD,NERRF1)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Add a single hit to a partially fitted track 
C
C     Input parameters 
C     ================
      INTEGER NADD     ! index of the hit in the DHRE bank
      INTEGER NERRF1   ! error multiplier from DFFIT via DFNEWW to DFITER
C
C     Output parameters 
C     =================
C     None
C
C     Author:  	       	  
C     =======
C-
C-    Originally from ARGUS collaboration
C-    Modified June 1996 A. Calcaterra
C-
C----------------------------------------------------------------------
C
C       Global Declarations:-
C       =====================
C
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$ITRK:CFLAGS.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'    

C       External Functions:-
C       ====================

      INTEGER BLOCAT

C       Local Declarations:-
C       ====================

      REAL      MAXTRP
      PARAMETER (MAXTRP=10.)

      LOGICAL CLOSE_E
      INTEGER STATUS,INDR,INDDATR,DHRENCO
      INTEGER N,NLST
      INTEGER NC,I,INDWIRE,ITRSAV,RSAV
      REAL    D2D,STEP,MIN_STEP,EXTRAP,PHIZ0
      REAL    A1,A2,CHIMLT
      REAL    C,C1,C2,CMIN,AX,AY,AZ

C-------  SPACE IN /CDFWORK/ EXHAUSTED. ADD NOTHING.

      IF (NDFC .GE. MXHIT-1) THEN
        CALL ERLOGR('DFADD',ERWARN,0,STATUS,
     +      'Working space exhausted.')
        RETURN
      ENDIF

C-------  LOCATE RUNNING VERSION OF BANK DHRE

      STATUS = BLOCAT(IW,'DHRE',2,INDR,INDDATR)
      IF (STATUS.NE.YESUCC) THEN
        CALL ERLOGR('DFADD',ERWARN,0,STATUS,
     +      'Bank DHRE not found.')
        RETURN
      ENDIF 
      INDR    = INDDATR+IW(INDDATR+DHRHDS)
      DHRENCO = IW(INDDATR+DHRNCO)
      INDWIRE   = INDR + (NADD-1)*DHRENCO

C------- FILL DF..(NC) ARRAYS. FIND FIRST EMPTY SLOT IN CDFWORK
C------- THERE *MUST* BE ONE BECAUSE OF THE TEST MADE ABOVE ON NDFC/MXHIT-1

      NC = 1
      DO WHILE (NDF(NC).GT.0 .OR. NC.EQ.NDFL)
        NC = NC+1
      ENDDO
      KDF(NC)   = NADD
      DFD(NC)   = ABS(RW(INDWIRE+DHRRAD)) !? BUT ...
      MDF(NC)   = 0
      LDFL(NC)  = IW(INDWIRE+DHRSLR)
      DFE(NC)   = RW(INDWIRE+DHRERR)**2
      DFA(5,NC) = 0.
      IDF(NC)   =  IW(INDWIRE+DHRWNR)
      PHIZ0     =  TIDDP(LDFL(NC)) * (IDF(NC)-1)
      DFVX(NC)  = -TIDST(LDFL(NC)) * SIN(PHIZ0)
      DFVY(NC)  =  TIDST(LDFL(NC)) * COS(PHIZ0)
      DFWX(NC)  =  TIDRA(LDFL(NC)) * COS(PHIZ0)
      DFWY(NC)  =  TIDRA(LDFL(NC)) * SIN(PHIZ0)

C-------  TRY TO FIND THE RIGHT PLACE IN THE PRESENT CHAIN OF HITS.
C-------  "NLST" IS THE INDEX OF THE LAST HIT IN THE CHAIN BEFORE "STEP"
C-------  BECOMES NEGATIVE. IF "NLST" TURNS OUT TO BE 0, THEN THE HIT TO 
C-------  BE ADDED IS THE FIRST ONE.
C-------  BUT BEFORE TRUSTING DFPNT ONE MUST FIRST GET "CLOSE ENOUGH"

      MIN_STEP = 1.E+14
      STEP = 1.
      NLST = 0
      N = NDF1
      CLOSE_E = .FALSE.
      DO WHILE (N.GT.0 .AND. STEP.GT.0.)
        D2D = SQRT((DFX(N)-DFWX(NC))**2+(DFY(N)-DFWY(NC))**2)
        IF (D2D.LT.50.) THEN
          CLOSE_E = .TRUE.
          CALL DFPNT(N,NC,STEP)
          IF (STEP.GT.0. .AND. STEP.LT.MIN_STEP) THEN
            MIN_STEP = STEP
            NLST     = N
          ENDIF
        ENDIF
        N = NDF(N)
      ENDDO
      IF (.NOT. CLOSE_E) THEN
        CALL INERR (453)
        RETURN
      ENDIF
      IF (NLST.GT.0) THEN
        CALL DFNEXT(NLST,NC,MIN_STEP)
        EXTRAP = SQRT((DFX(NC)-DFX(NLST))**2+(DFY(NC)-DFY(NLST))**2)
        CHIMLT = 1.
      ELSE
        CALL DFNEXT(NDF1,NC,STEP)
        EXTRAP = SQRT((DFX(NC)-DFX(NDF1))**2+(DFY(NC)-DFY(NDF1))**2)
        CHIMLT = 5.
      ENDIF

C-------  REJECT EXTRAPOLATIONS TOO BIG	       	       	       	       	 

      IF (EXTRAP .GT. MAXTRP) THEN
        RETURN
      ENDIF

C-------  CHISQ CONTRIBUTION OF THE NEW WIRE; FIND SIGN OF DRIFT DISTANCE

      A1 = TIDSC(LDFL(NC))
      AX = DFVY(NC) * DFPZ(NC) -   A1     * DFPY(NC)
      AY =   A1     * DFPX(NC) - DFVX(NC) * DFPZ(NC)
      AZ = DFVX(NC) * DFPY(NC) - DFVY(NC) * DFPX(NC)
      A2 = AX**2 + AY**2 + AZ**2
      A1 = SQRT(A2)
      C = ((DFWX(NC) - DFX(NC)) * AX +
     +       (DFWY(NC) - DFY(NC)) * AY - DFZ(NC) * AZ ) / A1
      C1 = (C + DFD(NC))**2 / DFE(NC)
      C2 = (C - DFD(NC))**2 / DFE(NC)

C-------  CUT ON CHI2: INCREASE IT BY FACTOR 5 IF EXTRAPOLATING BACKWARD

      CMIN = AMIN1(C1,C2)
      IF (CMIN .GT. CHIMLT*CDFCAD) RETURN
      IF (CMIN.EQ.C2) THEN
        DFD(NC) = -DFD(NC)
      ELSE
      ENDIF

C-------  WE HAVE A CANDIDATE: IT MUST BE MARKED, WITH THE RIGHT SIGN, BOTH   
C-------  IN DHRE (BECAUSE DFITER--> DFBCOR WILL READ FROM THERE) AND IN DFD.
C-------  IF THE FIT IS ATTEMPTED, AND FAILS, THE ORIGINAL VALUES WILL
C-------  BE RECOVERED FROM ITRSAV AND RSAV.

      ITRSAV = IW(INDWIRE+DHRTRN)
      IW(INDWIRE+DHRTRN) = ITR
      RSAV = RW(INDWIRE+DHRRAD)
      RW(INDWIRE+DHRRAD) = DFD(NC)
      NDFC   = NDFC+1
      IF (TIDST(LDFL(NC)) .LT. 0.) NFITNEG = NFITNEG+1
      IF (TIDST(LDFL(NC)) .GT. 0.) NFITPOS = NFITPOS+1

      IF (NLST .EQ. 0) THEN

C-------  THIS HIT MUST BE ADDED BEFORE THE FIRST ONE

        NDF(NC) = NDF1
        DFS(NC) = -STEP
        DFL(NC) = 0.
        NDF1 = NC
        N = NDF1
        DO WHILE (NDF(N).GT.0)
          DFL(NDF(N)) = DFL(N) + DFS(N)
          N = NDF(N)
        ENDDO
        NDFMS(1) = NC
        MDF(NC) = 0
        DFCTGT = DFPZ(NC) / SQRT (DFPX(NC)**2 + DFPY(NC)**2)
        DFSTHE = 1. / SQRT (1. + DFCTGT**2)
        DFPHI  = ATAN2 (DFPY(NC) , DFPX(NC))
      ELSEIF (NLST .EQ. NDFL) THEN

C-------  THIS HIT MUST BE ADDED AFTER THE  LAST ONE

        NDF(NDFL) = NC
        NDF(NC) = 0
        DFS(NDFL) = MIN_STEP
        DFL(NC) = DFL(NDFL) + DFS(NDFL)
        NDFL = NC
      ELSE

C-------  THIS HIT MUST BE ADDED IN THE MIDDLE OF THE CHAIN
        NDF(NC)   = NDF(NLST)
        NDF(NLST) = NC
        DFS(NC)   = DFS(NLST) - MIN_STEP
        DFS(NLST) = MIN_STEP
        DFL(NC)   = DFL(NLST) + DFS(NLST)
      ENDIF

C-------  CLEAR DERIVATIVES

      DO I=1,NDFDIM
        DFA(I,NC) = 0.
      ENDDO

C-------  ATTEMPT THE FIT NOW (IF THE POINT IS NOT REALLY TOO CLOSE: CDFDC1) 
C-------     IF IT WORKS, SAVE NEW HIT INCREASING NDFC
C-------     IF IT DOES NOT, CALL DFKILL TO CLEAN UP VECTORS
C-------  IF THE HIT *IS* REALLY TOO CLOSE DO NOT WASTE TIME: LEAVE ALL SUCH
C-------  HITS IN THEIR VECTORS, FOR THE LAST ITERATION IN DFFIT.

      IF (CMIN .GT. CDFDC1) THEN
      
C------- Let's save current situation

        NDFERR = 0 
        IF(NLST.eq.0) NLST = NDFL
        CALL DFSAVE(NLST,.FALSE.)

        CALL DFITER (NERRF1*CDFDC1,1.)
        IF (NDFERR.EQ.0) THEN
        ELSE

C-------  RECOVER ORIGINAL VALUES IN DHRE

          IW(INDWIRE+DHRTRN) = ITRSAV
          RW(INDWIRE+DHRRAD) = RSAV

C-------  let's restore all vital track info !

          CALL DFRESTORE(NLST,.FALSE.)

          CALL DFKILL(NC)
          IF (NDFERR.NE.0) RETURN
         ENDIF
      ELSE
      ENDIF

      RETURN
      END
C
C*DK DFBCOR
C
C=======================================================================
C
      SUBROUTINE DFBCOR
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : To correct the determination of drift distances
C                          applying fine space-time relations, depending
C                          on the phi impact angle of the track and on
C                          the particular local shape of the cells.
C     Author: A. Calcaterra
C     =======
C-
C-    Created  17-1-96
C-
C----------------------------------------------------------------------
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$INC:BPOYBS.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:CCONST.INC'
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC' 

      INTEGER STATUS,BLOCAT,FINEST
      INTEGER INDC,INDDATC,DTCENCO,INDR,INDDATR,DHRENCO
      INTEGER N,LGEANFI,CELLDIM
      REAL*4  BETA,PHITILDE
      REAL*4  TZCOR,PREV_R,DRIFTR,ERRD

      STATUS = BLOCAT(IW,'DTCE',2,INDC,INDDATC)
      IF (STATUS.NE.YESUCC) RETURN
      DTCENCO = IW(INDDATC+DTCNCO)
      INDC = INDDATC+IW(INDDATC+DTCHDS)
      STATUS = BLOCAT(IW,'DHRE',2,INDR,INDDATR)
      IF (STATUS.NE.YESUCC) RETURN
      DHRENCO = IW(INDDATR+DHRNCO)
      INDR = INDDATR+IW(INDDATR+DHRHDS)

      N = NDF1
      DO WHILE (N.GT.0)
       IF (LDFL(N) .GT. 0) THEN

C  Translate layer n. from the ARGUS to the GEANFI convention

         LGEANFI = 1+2*(59-LDFL(N))
         CELLDIM = 3
         IF (LDFL(N).GT.46) CELLDIM = 2

C  Now calculate beta and phitilde for this particular hit,cell and track

         CALL DFCBET(IDF(N),LGEANFI,
     .               DFX(N),DFY(N),DFZ(N),
     .               BETA,PHITILDE)
         IF (BETA.LT.65.) BETA = 65.
         IF (BETA.GT.130.) BETA = 130.
         DFB(N) = BETA
         DFF(N) = PHITILDE

C  Finally recalculate drift distance from the Z-corrected drift time

         TZCOR = ABS(RW(INDC+(KDF(N)-1)*DTCENCO+DTCTIM))
         STATUS = FINEST(CELLDIM,TZCOR,
     .                   BETA,PHITILDE*180./PI,
     .                   DRIFTR,ERRD)
         PREV_R = RW(INDR+(KDF(N)-1)*DHRENCO+DHRRAD)
         RW(INDR+(KDF(N)-1)*DHRENCO+DHRRAD) = SIGN(DRIFTR,PREV_R)
         RW(INDR+(KDF(N)-1)*DHRENCO+DHRERR) = ERRD

C  Assume that big changes should not change signs. 
C  Small ones don't matter.

         DFD(N) = SIGN(DRIFTR,PREV_R)
         DFE(N) = ERRD**2
       ENDIF
       N = NDF(N)
      ENDDO

      RETURN
      END
C
C*DK DFTCOR
C
C=======================================================================
C
      SUBROUTINE DFTCOR
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : To correct the determination of drift times
C                          taking into account time propagation of the
C                          signal along the wire, which depends on Z,
C                          and the particle's time of flight.
C     Author: A. Calcaterra
C     =======
C-
C-    Created  17-1-96
C-
C----------------------------------------------------------------------
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$INC:BPOYBS.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'

      INTEGER BLOCAT

      INTEGER STATUS,IND1,INDDAT1,IND2,INDDAT2,NHITC,DTCENCO
      INTEGER N,LGEANFI
      REAL*4 TMEAS,TPROP,TZCOR
      LOGICAL ODDLAY
      REAL*4 VINV,ALENGBY2
      DATA VINV/0.035/,ALENGBY2/155./      

      STATUS = BLOCAT(IW,'DTCE',1,IND1,INDDAT1)
      IF (STATUS.NE.YESUCC) RETURN
      STATUS = BLOCAT(IW,'DTCE',2,IND2,INDDAT2)
      IF (STATUS.NE.YESUCC) RETURN

      NHITC   = IW(INDDAT1+DTCNRO)
      DTCENCO = IW(INDDAT1+DTCNCO)
      IND1 = INDDAT1+IW(INDDAT1+DTCHDS)
      IND2 = INDDAT2+IW(INDDAT2+DTCHDS)
      N = NDF1
      DO WHILE (N.GT.0)
        IF (LDFL(N) .GT. 0) THEN
          TMEAS = RW(IND1+(KDF(N)-1)*DTCENCO+DTCTIM)
          LGEANFI = 59-LDFL(N)
          ODDLAY = BTEST(LGEANFI,0)
          IF (ODDLAY) THEN
            TPROP = (ALENGBY2 - DFZ(N))*VINV
          ELSE
            TPROP = (ALENGBY2 + DFZ(N))*VINV
          ENDIF

C  Times from MC are signed like drift distances: so take the ABS()

          TZCOR = ABS(TMEAS) - TPROP
          TZCOR = TZCOR-(DFL(N)+RW(JDPRS+DPRCEN))/(DFBETA*30.)

C  Assume that big changes should not change signs. 
C  Small ones don't matter.

          RW(IND2+(KDF(N)-1)*DTCENCO+DTCTIM) = SIGN(TZCOR,TMEAS)
        ENDIF
        N = NDF(N)
      ENDDO

      RETURN
      END
C
C*DK DFCBET
C=======================================================================
C
      SUBROUTINE DFCBET(ISENSE,NPLANE,XHIT,YHIT,ZHIT,BETA,PHITILDE)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Finds the cell shape 
C
C     Input parameters 
C     ================
C     INTEGER ISENSE   ! index of the hit sense wire
C     INTEGER NPLANE   ! index of the hit sense wire plane
C     REAL*4  XHIT     ! X coordinate of the point of closest approach
C     REAL*4  YHIT     ! Y coordinate of the point of closest approach
C     REAL*4  ZHIT     ! Z coordinate of the point of closest approach
C
C     Output parameters 
C     =================
C     REAL*4  BETA     ! angle that identifies the shape of the cell 
C     REAL*4  PHITILDE ! angle of the point of closest approach
C                      ! in the local reference system of the hit cell 
C
C     Author: P. de Simone
C     =======
C-
C-    Created  8-1-96   
C-
C----------------------------------------------------------------------
      INTEGER ISENSE, NPLANE
      REAL*4  XHIT, YHIT, ZHIT
      REAL*4  BETA, PHITILDE
$$INCLUDE 'K$ITRK:CCONST.INC'
$$INCLUDE 'RTDB$LIBRARY:GFGEOM.INC'
C
C  Local declaration
C
      INTEGER NF, IDFIELD, ISFIELD
      REAL*4  PHI1, PHI2, PHI3, PHI4, PHI5
      REAL*4  R1Z, R3Z, R4Z
      REAL*4  X1, Y1, X2, Y2, X3, Y3, X4, Y4, X5, Y5
      REAL*4  XP, YP, XF, YF
      REAL*4  PHIZ, PHIF, PHID, PHIS
      REAL*4  XD, YD, XS, YS
      REAL*4  DD, DS  
      REAL*4  DX24, DY24, DX34, DY34, D24, D34
      REAL*4  COSB
      REAL*4  DX, DY, D, DX51, DY51, D51
      REAL*4  COSP, RAGG
C
C--Definition of BETA and PHITILDE
C
C       4     3
C       o-----o     o
C      /_/ beta
C     /  
C  2 o   1 +     o
C  
C
C    o     o     o 
C
C   Calculate the PHITILDE angle, i.e. the "angle" of closest approach,
C   which is an approximation of the direction of approach of the first
C   cluster. The cells are divided in 36 PHITILDE wedges of +-5 degrees 
C   so that the appropriate STR can be chosen. For each of the 36 PHITILDE
C   wedges there are 6 (all?)different STRs computed for 6 different BETAs 
C
C     o       o       o
C
C          x (hit)
C           \        
C            \--\ <-- phitilde
C     o       X__\____o --> wire 5
C
C
C
C
C     o       o       o
C
C ----------------------------------
 
C  find the phi angle of the sense wire on the plane z = 0
   
      PHI1 = (ISENSE-1)*(2.*DTETWI(NPLANE))

C  find the coordinates of the sense wire on the plane z = hit(3)

      R1Z  = RP0(NPLANE)*RP0(NPLANE) + 
     >       ZHIT*ZHIT*TSTE(NPLANE)*TSTE(NPLANE)
      R1Z  = SQRT(R1Z)
      X1   = RP0(NPLANE)*COS(PHI1) - ZHIT*SIN(PHI1)*TSTE(NPLANE)
      Y1   = RP0(NPLANE)*SIN(PHI1) + ZHIT*COS(PHI1)*TSTE(NPLANE)

C  find the phi angle of the sense wire on the plane z = hit(3)

      PHIZ = ATAN2(Y1,X1)
      IF ( PHIZ.LT.0. ) PHIZ = PHIZ + PI2

C Calculate Phitilde. Find coordinate of field wire 5 (see above)
C on the plane Z=Zhit

      PHI5 = PHIZ - DTETWI(NPLANE)
      IF (PHI5.LT.0.) PHI5 = PHI5 + PI2
      X5 = R1Z*COS(PHI5)
      Y5 = R1Z*SIN(PHI5)

C vector from the hit to the sense wire

      DX   = XHIT - X1
      DY   = YHIT - Y1
     D    = DX*DX + DY*DY

C vector from the field wire 5 (see drawing) to the sense wire

      DX51 = X5 - X1
      DY51 = Y5 - Y1
      D51  = DX51*DX51 + DY51*DY51

      IF ((D.NE.0.0).AND.(D51.NE.0.0)) THEN
       COSP = ( DX*DX51 + DY*DY51 )/SQRT(D*D51) 
      ELSE
       COSP = 0.0
      ENDIF
      IF (ABS(COSP).GT.0.99999) COSP = SIGN(0.99999,COSP)

      RAGG  = XHIT*XHIT + YHIT*YHIT
      RAGG  = SQRT(RAGG)

      IF( R1Z.LT.RAGG ) THEN
         PHITILDE = ACOS(COSP)
      ELSE
         PHITILDE = PI2 - ACOS(COSP)
      ENDIF 
 
C  find the coordinates of field wire 2 on the plane z = hit(3)
      PHI2 = PHIZ + DTETWI(NPLANE)
      IF (PHI2.GT.PI2) PHI2 = PHI2 - PI2
      X2   = R1Z*COS(PHI2)
      Y2   = R1Z*SIN(PHI2)
      
C  find the coordinates of field wire 3 on the plane z = hit(3)
 
      NF   = NPLANE + 1
      R3Z  = RP0(NF)*RP0(NF) + ZHIT*ZHIT*TSTE(NF)*TSTE(NF) 
      R3Z  = SQRT(R3Z) 

C  1. project the coord X1 and Y1 on the hyperboloid nf at z = hit(3)

      XP   = X1*(R3Z/R1Z)
      YP   = Y1*(R3Z/R1Z)

C  2. calculate the phi angle PHIF at the plane z = hit(3)
C     of the first wire at R = RP0(NF) that has phi = 0 at z = 0

      XF   = RP0(NF)
      YF   = ZHIT*TSTE(NF)
      PHIF = ATAN2(YF,XF) 

C  3. index and phi angle of the field wires on the right 
C     and on the left of (XP,YP) on the plane z = hit(3)

      IF( PHIF.LT.0 ) THEN 
          PHIF    = - PHIF
          IDFIELD = INT( (PHIZ+PHIF)/DTETWI(NF) )
          PHID    = DTETWI(NF)*IDFIELD - PHIF   
          ISFIELD = IDFIELD + 1
          PHIS    = DTETWI(NF)*ISFIELD - PHIF             
      ELSE
          IDFIELD = INT( (PHIZ-PHIF)/DTETWI(NF) )
          PHID    = DTETWI(NF)*IDFIELD + PHIF   
          ISFIELD = IDFIELD + 1
          PHIS    = DTETWI(NF)*ISFIELD + PHIF   
      ENDIF      

C  4. find the coordinate of the two found field wires and take the
C     closest to the projection of the sense wire (XP,YP)

      XD   = R3Z*COS(PHID)
      YD   = R3Z*SIN(PHID)
      XS   = R3Z*COS(PHIS)
      YS   = R3Z*SIN(PHIS)

      DD   = SQRT((XP-XD)**2 + (YP-YD)**2)
      DS   = SQRT((XP-XS)**2 + (YP-YS)**2)

      IF ( DD.GT.DS ) THEN
        X3   = XS
        Y3   = YS
        PHI3 = PHIS
      ELSE
        X3   = XD
        Y3   = YD
        PHI3 = PHID
      ENDIF

C  find the coordinate of the field wire 4 on the plane z = hit(3)
 
      PHI4 = PHI3 + DTETWI(NF)
      R4Z  = R3Z
      X4   = R4Z*COS(PHI4)
      Y4   = R4Z*SIN(PHI4)

C  define the auxiliary vectors

  10  DX24 = X2 - X4
      DY24 = Y2 - Y4
      DX34 = X3 - X4
      DY34 = Y3 - Y4
      D24  = DX24*DX24 + DY24*DY24
      D34  = DX34*DX34 + DY34*DY34

C  .. and calculate the beta angle

      COSB = (DX24*DX34 + DY24*DY34)/SQRT(D24*D34)
      BETA = ACOS(COSB)*180./PI

      IF ( BETA.GE.65. ) RETURN

      PHI4 = PHI3
      PHI3 = PHI3 - DTETWI(NF)
      X3   = R3Z*COS(PHI3)
      Y3   = R3Z*SIN(PHI3) 
      X4   = R4Z*COS(PHI4)
      Y4   = R4Z*SIN(PHI4)
      GO TO 10

      END
C      
C*DK DFDRV
C
C=======================================================================
C
      SUBROUTINE DFDRV
$$IMPLICIT

C------- CALCULATE DERIVATIVES, CHISQ, AND FILL MATRIX

$$INCLUDE 'C$INC:JOBSTA.INC'
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$INC:BCS.INC'
$$include  'K$ITRK:CDFWORK.INC'


      REAL X1,Y1,Z1
      REAL PX1,PY1,PZ1
      REAL PXN1,PYN1,XN,YN
      REAL A1,A2,AX,AY,AZ,H1
      REAL BTHETA,N1A,B1A,PHIMS
      REAL THETAMS,TMS
      INTEGER I,J,ND,N,ND1,M
      INTEGER NPRHITS

      X1 = DFX(NDF1)
      Y1 = DFY(NDF1)
      Z1 = DFZ(NDF1)
      PX1 = DFPX(NDF1)
      PY1 = DFPY(NDF1)
      PZ1 = DFPZ(NDF1)                                 
      PXN1 = -PY1 / DFSTHE
      PYN1 =  PX1 / DFSTHE

C------- CLEAR XX AND YY

      DFCHI2 = 0.0
      DO I=1,NDFDIM+2
        YY(I) = 0.D0
        DO J=1,NDFDIM+2
          XX(I,J) = 0.D0
        ENDDO
      ENDDO
      ND = 6

      N = NDF1
      DO WHILE (N.NE.0)
        IF (LDFL(N).LE.0)  GO TO 400
        XN = DFX(N)
        YN = DFY(N)

C------- FORM VECTOR A = WIRE CROSS TANGENT (CF NIM(42))

        A1 = TIDSC(LDFL(N))
        AX       = DFVY(N) * DFPZ(N) -   A1    * DFPY(N)
        AY       =   A1    * DFPX(N) - DFVX(N) * DFPZ(N)
        AZ       = DFVX(N) * DFPY(N) - DFVY(N) * DFPX(N)
        A2 = AX**2 + AY**2 + AZ**2
        A1 = SQRT(A2)
        AX       = AX       / A1
        AY       = AY       / A1

C------- CALCULATE DERIVATIVES (STEREO WIRES)
C------- CF NIM(50-54)

C ---           DFA(1,N) =  D DIST / D D
C ---           DFA(2,N) =  D DIST / D Z0
C ---           DFA(3,N) =  D DIST / D CURV
C ---           DFA(4,N) =  D DIST / D CTG(THETA)
C ---           DFA(5,N) =  D DIST / D (DP/DX)  dummy !!!!
C ---           DFA(6,N) =  D DIST / D PHI

        DFA(1,N) = PXN1 * AX + PYN1 * AY
        DFA(2,N) = AZ / A1
        H1 = (X1 - XN)*AX + (Y1 - YN)*AY + (Z1 - DFZ(N))*DFA(2,N)
        DFA(3,N) = H1 / DFKURV
        DFA(4,N) = DFL(N) * DFA(2,N) * DFSTHE
        DFA(5,N) = 0.
        DFA(6,N) = (XN-X1)*AY - (YN-Y1)*AX
        ND1 = MAX0 (6,ND)
        DO M=7,ND1,2
          DFA(M,N) = (XN-DFX(NDFMS(M-5)))*AY 
     +               - (YN-DFY(NDFMS(M-5)))*AX

          PHIMS=ATAN2(DFPY(NDFMS(M-4)),DFPX(NDFMS(M-4)))
          N1A=SIN(PHIMS)*AX-COS(PHIMS)*AY
          B1A=COS(PHIMS)*AX+SIN(PHIMS)*AY
          THETAMS=ASIN(DFSTHE)
          BTHETA=(DFL(N)-DFL(NDFMS(M-4)))
     +           *DFH(N)*DFKURV*SIN(THETAMS)
          DFA(M+1,N)=(DFL(N)-DFL(NDFMS(M-4)))
     +    *COS(THETAMS)*( SIN(BTHETA)*N1A+COS(BTHETA)*B1A
     +     - TAN(THETAMS)*DFA(2,N) )

        ENDDO

C------- CHISQ CONTRIBUTION - CF NIM(21,43)

        DFCH(N) = DFD(N) + (DFWX(N) - XN) * AX +
     +                   (DFWY(N) - YN) * AY - DFZ(N)  * DFA(2,N)
        DFCHI2 = DFCHI2 + DFCH(N)**2 / DFE(N)

C------- FILL MATRIX AND VECTOR - CF NIM(28)

        DO I=1,ND
          YY(I) = YY(I) + DFA(I,N) * DFCH(N) / DFE(N)
          DO J=1,I
            XX(I,J) = XX(I,J) + DFA(I,N) * DFA(J,N) / DFE(N)
          ENDDO
        ENDDO

  400   IF (NDFMS(ND-4).EQ.N)  ND = ND + 2
        N = NDF(N)
      ENDDO

C------- MULTIPLE SCATTERING CONSTRAINT
C------- DFEMS=1/SIGMA_SQUARE_MS   - CF  NIM(56)

      XX(5,5) = 1.
      IF (NDFDIM .GT. 5) THEN
        DO I=7,NDFDIM
          XX(I,I) = XX(I,I) + DFEMS(I-5)
          YY(I) = YY(I) - (DFPMS(I-5)) * DFEMS(I-5)
        ENDDO
      ENDIF

      RETURN
      END
C
C*DK DFFIT
C
C=======================================================================
C
      SUBROUTINE DFFIT (NPASS)
$$IMPLICIT
      INTEGER NPASS

C=======  FIT ONE TRACK

$$INCLUDE 'C$INC:JOBSTA.INC'
$$INCLUDE 'K$ITRK:CFLAGS.INC'
$$include  'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE  'K$ITRK:CDFWORK.INC'


	integer npass2                        
	common /NP/npass2       !<COM9-11

C       External Functions:-
C       ====================

C       Local Declarations:-
C       ====================
      INTEGER KINKPOS,KINK_FLAG

      INTEGER NPRHITS
      INTEGER NHITS1,NHITS2,NHITS3,NHITS4,
     +        SHITS1,SHITS2   
      INTEGER NERRF1,NERRF2,IFLREV,N,I,M,I1
      REAL    RESID
      REAL    CH2A,CH2B
      REAL ANG1,ANG2
      COMMON /ANGLES/ ANG1(64),ANG2(64)
      COMMON /NBHITS/ NPRHITS 
      COMMON /CH2AB/ CH2A(MXHIT),CH2B(MXHIT)

C=======  SET FLAGS

      NERRF1=1
      NERRF2=1
      KINK_FLAG = 0
      
c     TOP OF LOOP OF NEXT TRIAL WITH LOOSER CHI2 CUTS

      IFLREV = -1
      NDFERR = 0
            
c NPRHITS : initial number of hits

      NPRHITS = IW(JDPRS+DPRPOS) + IW(JDPRS+DPRNEG)

C     LOOP BACK TO THIS POINT IN CASE OF WIRE-REVERSING

 10   CONTINUE

C=======  1ST ITERATION

      npass2= npass 

      DO M=1,64
         ANG1(M) = 0.
         ANG2(M) = 0.
      ENDDO         

      CALL DFINIT (1,NPRHITS)

C  Check that the track left a sufficient number of hits, with a sufficient
C  number of stereo layers etc. etc.

      IF (NFITPOS+NFITNEG .LE. NCUTSTEREO) THEN
        NDFERR = 8
        CALL INERR(416)
        GOTO 888
      ELSE
        IF (NFITPOS.LT.3 .OR. NFITNEG.LT.3) THEN
          NDFERR = 8
          CALL INERR(416)
          GOTO 888
        ENDIF 
      ENDIF
      
C  Check that the track crossed a sufficient number of different layers.

      IF (NL_CR .LT. 2) THEN
        NDFERR = 9
        CALL INERR(407)
        GOTO 888
      ENDIF

      CALL DFTRAC(.FALSE.)

      FDFAST = .FALSE.
      NDFINV = 0
      NDFDIM = 6

 100  CALL DFITER (NERRF1*CDFDC1,CDFM1L)
      IF (NDFERR.NE.0) THEN
         NERRF1=NERRF1+1
         CALL INERR(408)

C  Some error conditions: (Chi2 increasing) and (too many iterations)
C  invite to try again the fit relaxing the first cut. The same could 
C  apply in principle for (pred chi2 wors), NDFERR=3

         IF (NDFERR.NE.2 .AND. NDFERR.NE.6) THEN
            GOTO 888
         ENDIF
         IF (NERRF1.LT.15) GOTO 100
      ENDIF
      FDFAST = .TRUE.

C=======  TRY FLIPPING SMALL DRIFT DISTANCES

      CALL DFLIP(NERRF1)


C=======  TRY TO FIND A KINK ALONG THE TRACK
C
C
      IF(KINK_RECO) THEN
         CALL DFKINK(ITR,KINKPOS,KINK_FLAG)
      ENDIF
C
C dE/dx part (particles are assumed to be pions)

        IF (ldfdx.GE.0) THEN
        
C+++++++++++++++++++++++++++++++++
C	if(nprhits.gt.80) then ! for n<80 no dedx correction   !<COM9-11
C+++++++++++++++++++++++++++++++++

 150      CALL DFDEDX(1)     
          CALL DFITER(NERRF2*CDFDC2,CDFM1L)

        IF (NDFERR.NE.0) THEN
           NERRF2=NERRF2+1
           CALL INERR(417)
           IF (NDFERR.NE.2 .AND. NDFERR.NE.6) then
C	     write(6,*) 'dedx - rej track, ndferr=',NDFERR 
           goto 888
	   ENDIF 
           IF (NERRF2.LT.15) THEN
             NDFERR = 0
             GOTO 150
           ENDIF
        ENDIF

C+++++++++++++++++++++++++++++++++ 
C	endif                        !<COM9-11
C+++++++++++++++++++++++++++++++++ 

      ENDIF

C=======  MULTIPLE SCATTERING

      IF (npass.eq.2.and.LDFMUS.GE.0) THEN
         CALL DFMUSC
      ENDIF

 200  IF (NDFDIM.GT.6) THEN
         CALL DFITER (NERRF1*CDFDC1,CDFM1L)
         IF (NDFERR.NE.0) THEN
            NERRF1=NERRF1+1
            CALL INERR(409)
            IF (NDFERR.NE.2 .AND. NDFERR.NE.6) THEN
               GOTO 888
            ENDIF
            IF (NERRF1.LT.15) GOTO 200
         ENDIF
      ENDIF

C=======  REJECT WIRE(S) OR SWITCH SIGNS OF DRIFT TIME

C NHITS1 : number of hits after drift distance sign flipping

      NHITS1 = NFITNEG+NFITPOS
      IF (LDFREJ.GE.0) CALL DFREJ (NERRF1,60.,4.)      !sv
      IF (NDFERR.NE.0) THEN
         CALL INERR(420)
         GOTO 888
      ENDIF

C=======  FIND NEW WIRES

c NHITS2 : number of hits after hit rejection (DFREJ)
c SHITS1 : number of rejected hits after 1st call to DFREJ
c NHITS3 : number of hits after hit addition

      NHITS2 = NFITNEG+NFITPOS
      SHITS1 = NHITS1-NHITS2
      IF (LDFADD.GE.0) THEN
        CALL DFNEWW(NERRF1)
        NHITS3 = NFITNEG+NFITPOS
        CALL HFILL(2,FLOAT(NHITS3-NHITS2),0.,1.)
      ENDIF

C======= REJECT WIRES, AGAIN

      IF (LDFREJ.GE.0) CALL DFREJ (NERRF1,60.,4.)  !sv
      IF (NDFERR.NE.0) THEN
         CALL INERR(421)
         GOTO 888
      ENDIF

c NHITS4 : number of hits after hit rejection (DFREJ)
c SHITS2 : number of rejected hits after 2nd call to DFREJ

      NHITS4 = NFITNEG+NFITPOS
      SHITS2 = NHITS3-NHITS4

C=======  MULTIPLE SCATTERING

      IF (npass.eq.1.and.LDFMUS.GE.0) CALL DFMUSC

 210  IF (NDFDIM.GT.6) THEN
         CALL DFITER (NERRF1*CDFDC1,CDFM1L)
         IF (NDFERR.NE.0) THEN
            NERRF1=NERRF1+1
            CALL INERR(409)
            IF (NDFERR.NE.2 .AND. NDFERR.NE.6) THEN
               GOTO 888
            ENDIF
            IF (NERRF1.LT.15) GOTO 210
         ENDIF
      ENDIF

C=======  LAST ITERATION ; GET ERROR MATRIX

      NDFINV = 6
 300  CALL DFITER (NERRF2*CDFDC2,CDFM1L)
      IF (NDFERR.NE.0) THEN
         NERRF2=NERRF2+1
         CALL INERR(410)		
         IF (NDFERR.NE.2 .AND. NDFERR.NE.6) THEN
            GOTO 888
         ENDIF
         IF (NERRF2.LT.15) GOTO 300
      ENDIF

C=======  IF EVERYTHING WORKED, PLOT RESIDUALS AND STORE RESULTS

C	nhi=0             !<COMM6-11
      IF (NDFERR .EQ. 0) THEN
        IF (ABS(DFCTGT) .LT. 1000.) THEN
          N = NDF1
          DO WHILE (N.GT.0) 
            IF (LDFL(N).GT.0)  THEN
              RESID = - DFCH(N)
              DO I=1,NDFDIM
               RESID = RESID + XX(I,NDFDIM+2) * DFA(I,N)
              ENDDO
              CALL HFILL(450,RESID/SQRT(DFE(N)),0.,1.)
            ENDIF
            N = NDF(N)
          ENDDO
          CALL DFSTOR(NPASS) 
        ELSE   ! THE FIT CONVERGED ALL RIGHT, BUT TO WHAT, GOD KNOWS.
          CALL INERR(492)
        ENDIF
      ENDIF

      IF (NDFERR .EQ. 0) THEN
         CALL HFILL(3,FLOAT(SHITS1+SHITS2),0.,1.)
      ENDIF
      
 888  Continue
C
C=====  PREPARES NEW DPRS BANKS IF A KINK HAS BEEN FOUND
C
      IF(KINK_RECO) THEN
         IF(KINK_FLAG.EQ.-1) CALL DFTWOPR(KINKPOS,ITR)
      ENDIF
C
C
      RETURN
      END
C
C*DK DFINIT
C
C=======================================================================
C
      SUBROUTINE DFINIT (NFIRST,NLAST)
$$IMPLICIT

C------  INITIALIZE TRACK FIT FOR ONE TRACK

C       Call Parameters:-
C       ================

      INTEGER NFIRST,NLAST

C       Global Declarations:-
C       =====================

$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$ITRK:CCONST.INC'
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC' 

C       External Functions:-
C       ====================

      INTEGER BLOCAT

C       Local Declarations:-
C       ====================

      INTEGER STATUS,INDR,INDDATR,DHRENCO,IND
      INTEGER NDIFF(MXHIT),TEST      
      LOGICAL DIFFER

      REAL X(3),H(3)
      REAL PHIZ0, PGEV, DIVSTEP, DIST2D
      INTEGER NC,IWIRE
      INTEGER NADD,NADDST,L
      LOGICAL ITERATE

      CALL VZERO(DFX,MXHIT)
      CALL VZERO(DFY,MXHIT)
      CALL VZERO(DFZ,MXHIT)

      CALL VZERO(DFWX,MXHIT)
      CALL VZERO(DFWY,MXHIT)

      CALL VZERO(DFPX,MXHIT)
      CALL VZERO(DFPY,MXHIT)
      CALL VZERO(DFPZ,MXHIT)

      CALL VZERO(DFS,MXHIT)
      CALL VZERO(DFL,MXHIT)
      CALL VZERO(LDFL,MXHIT)

*  dhre bank (INDR,INDDATR)

      STATUS = BLOCAT(IW,'DHRE',2,INDR,INDDATR)
      INDR = INDDATR+IW(INDDATR+DHRHDS)
      DHRENCO = IW(INDDATR+DHRNCO)

C------  GET HELIX STARTING PARAMETERS
C------  DFKURV = 1/(RHO*HFIELD)  - CF NIM(37)

      NDF1 = 1
      DFKURV = RW(JDPRS+DPRCUR)
      DFCTGT = RW(JDPRS+DPRCTT)
      DFSTHE = 1. / SQRT (1. + DFCTGT**2)
      PGEV = 1./ABS(DFKURV*DFSTHE)
      
C------  BETA IN THE PION MASS HYPOTHESIS

      DFBETA = PGEV/SQRT(PGEV**2+PION_MASS**2)
      DFPHI  = RW(JDPRS+DPRPHI)
      NDFMS(1) = NDF1
      NDFMS(2) = 0
      DFDPDX = 0.
      DFCMSO = 0.
      DFCMS2 = 0.
      DFX(1) = RW(JDPRS+DPRXCO)
      DFY(1) = RW(JDPRS+DPRYCO)
      DFZ(1) = RW(JDPRS+DPRZCO)
      DFPY(1) = SIN (DFPHI) * DFSTHE
      DFPX(1) = COS (DFPHI) * DFSTHE
      DFPZ(1) = DFCTGT * DFSTHE
      DFSTLC = SQRT (CDFACU/ABS(DFKURV)) / DFSTHE

C          DFSTCL = SQRT (2 * RHO * ACCURACY)/SIN(THETA)
C--------  IS MAX STEP LENGTH FOR WHICH STRAIGHT LINE EXTRAPOLATION
C          IS ACCURATE WITHIN  CDFACU = 200 MICRON (JAN 95) 
C          SEE KAPITZA (65)

      DFH(1) = TIFLAV

      X(1) = DFX(1)
      X(2) = DFY(1)
      X(3) = DFZ(1)
      CALL MGFLD(X,H)

      CALL VSCALE(H,CONVERS,H,3)
      DFHX(1) = H(1) / DFH(1)
      DFHY(1) = H(2) / DFH(1)
      DFHZ(1) = H(3) / DFH(1)

      NC = 0
      NFITPOS = 0
      NFITNEG = 0
      NL_CR = 0

      L = NFIRST
      ITERATE = .TRUE.
      DO WHILE (L.LE.NLAST .AND. ITERATE)
        NC      = NC + 1
        
C--------  DFINIT MAY BE CALLED AGAIN, AFTER A HIT-REJECTION STEP.
C--------  FOR NOW, WE DECIDE TO RE-ACCEPT THE HIT ...

        IWIRE   = IABS(IW(JDPRS1+DPRLWI*(L-1)+DPRIWI))
        NDF(NC) = NC + 1
        DIST2D  = RW(JDPRS1+DPRLWI*(L-1)+DPRWTR)
        
C--------------------- 2D distances greater than 20 cm are not plausible
C--------------------- and they may make DFTRAC to loop forever

        DFS(NC) = AMIN1(DIST2D,20.) / DFSTHE
        DFL(NC) = 0.

C--------------------- FILL DF..(NC) ARRAYS

        IND       = INDR + (IWIRE-1)*DHRENCO
        KDF(NC)   = IWIRE
        IDF(NC)   = IW(IND+DHRWNR)
        MDF(NC)   = 0
        DFD(NC)   = RW(IND+DHRRAD)
        LDFL(NC)  = IW(IND+DHRSLR)
        DFE(NC)   = RW(IND+DHRERR)**2
        DFA(5,NC) = 0.
        PHIZ0     =  TIDDP(LDFL(NC)) * (IW(IND+DHRWNR)-1)
        DFVX(NC)  = -TIDST(LDFL(NC)) * SIN(PHIZ0)
        DFVY(NC)  =  TIDST(LDFL(NC)) * COS(PHIZ0)
        DFWX(NC)  =  TIDRA(LDFL(NC)) * COS(PHIZ0)
        DFWY(NC)  =  TIDRA(LDFL(NC)) * SIN(PHIZ0)
        IF (TIDST(LDFL(NC)) .LT. 0.) NFITNEG = NFITNEG + 1
        IF (TIDST(LDFL(NC)) .GT. 0.) NFITPOS = NFITPOS + 1
        DIFFER = .TRUE.
        DO TEST=1,NL_CR
          IF (LDFL(NC) .EQ. NDIFF(TEST)) DIFFER = .FALSE.
        ENDDO
        IF (DIFFER) THEN
          NL_CR = NL_CR + 1
          NDIFF(NL_CR) = LDFL(NC)
        ENDIF

C--------  INSERT ADDITIONAL STEPS IF STEP LENGTH TOO LARGE

        IF (DFS(NC) .GT. CDFSTL)  THEN
          NADDST  = DFS(NC) / CDFSTL
          DIVSTEP = DFS(NC) / (NADDST+1)
          DFS(NC) = DIVSTEP
          DO NADD=NC+1,MIN0(NC+NADDST,MXHIT)
            DFS(NADD)  = DIVSTEP
            NDF(NADD)  = NADD + 1
            KDF(NADD)  = 0
            MDF(NADD)  = 0
            DFCH(NADD) = 0.
            LDFL(NADD) = 0
          ENDDO
          NC = NC+NADDST
        ENDIF

C  Here the condition for iterating the loop is calculated

        ITERATE = NC+1 .LE. MXHIT-1
        L = L + 1
      ENDDO

C  Now flag premature termination of the loop, just to know

      IF (L.LT.NLAST) THEN
        CALL INERR (405)
      ENDIF

      DFS(NC) = 0.
      NDF(NC) = 0
      NDFL = NC
      NDFC = NC

      RETURN
      END
C            
C*DK DFITER
C
C=======================================================================
C
      SUBROUTINE DFITER (CUTCHI,CMAX1L)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : This routine minimizes the track chi-square
C-                         doing a maximum of "LDFITE" iterations.
C-                         The outputs are : a chi-2 value in DFCHIN,
C-                         the fitted set of 5 helyx parameters, and
C-                         the full series of points of closest approach
C-                         to the wires (indirectly, via the cumulative
C-                         flight distances DFL for example)
C-                         (All of this meaningful only if NDFERR = 0 ....)
C-
C-   Created
C-   Updated
C-
C----------------------------------------------------------------------
$$INCLUDE 'C$INC:JOBSTA.INC'
$$INCLUDE 'K$ITRK:CFLAGS.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'  ! 9/6/98 MXHIT=250


      INTEGER NDFITE,M,N,I,NPRHITS
      REAL    CUTCHI,CMAX1L
      REAL    X,CH2,CH2A,CH2B,DELTA
      LOGICAL TOLERATE,FAST_SWIM
      COMMON /NBHITS/ NPRHITS 
      COMMON /CH2AB/ CH2A(MXHIT),CH2B(MXHIT)

      NDFERR = 0
      DFCHIO = 1.E38
      DFNDGF = NFITNEG + NFITPOS - 5.
      
      TOLERATE = .TRUE.

      DO NDFITE=1,LDFITE

C-------  TRACE PARTICLE: FIND POINTS OF CLOSEST APPROACH TO THE WIRES

        FAST_SWIM = NDFITE .GT. 1
        CALL DFTRAC(FAST_SWIM)
        IF (NDFERR.NE.0) THEN
        
C------- THE ONLY ERROR IN DFTRAC IS SIGNALLED IN DFTRAC ITSELF

          RETURN
        ENDIF

C-------  USE POINTS OF C.A. TO IMPROVE CALCULATION OF DRIFT DISTANCES.
C-------  DO 1) Z-DEPENDENT CORRECTION OF TIME FOR PROPAGATION ALONG WIRE
C-------     2) CHOOSE PHI AND BETA-DEPENDENT SPACE-TIME RELATION

        IF (NDFITE.EQ.1 .AND. TS_RAWREL) CALL DFTCOR
        IF (NDFITE.EQ.1 .AND. TS_FINEREL)CALL DFBCOR

C-------  CALCULATE DERIVATIVES AND DFCHI2, DIAGONAL CHI-SQUARE
C-------  WITH CONTRIBUTIONS ONLY FROM MEASUREMENTS.
C-------  DFCMS2 IS CALCULATED BELOW, HERE IN DFITER.

        CALL DFDRV

        X = DFCHI2 + DFCMS2 - DFCHIO - DFCMSO
        IF (X.GT.0.1 .AND. NDFITE.GT.1)  THEN

C--------  CHISQ INCREASED SINCE LAST ITERATION.
C--------  DURING A GIVEN FIT THIS IS ACTUALLY ALLOWED, BUT ONLY ONCE.

           IF (TOLERATE) THEN
             TOLERATE = .FALSE.
           ELSE
             CALL INERR (412)
             NDFERR = 2
             RETURN
           ENDIF

        ENDIF

        DFCHIO = DFCHI2
        DFCMSO = DFCMS2

C--------  INVERT MATRIX; IF SINGULAR MATRIX, SIGNAL ERROR AND RETURNS

        CALL LEQU64 (XX,XI,YY,NDFDIM,NDFINV,NDFERR)
        IF (NDFERR.NE.0) THEN
          CALL INERR (411)
          RETURN
        ENDIF

C--------  CALCULATE THE NEW TRACK PARAMETERS

        DFX(NDF1) = DFX(NDF1) - DFPY(NDF1) * XX(1,NDFDIM+2) / DFSTHE
        DFY(NDF1) = DFY(NDF1) + DFPX(NDF1) * XX(1,NDFDIM+2) / DFSTHE
        DFZ(NDF1) = DFZ(NDF1) + XX(2,NDFDIM+2)
        DFKURV = DFKURV + XX(3,NDFDIM+2)
        IF (ABS(DFKURV).LE.1.E-10) THEN
           NDFERR=10
           RETURN
        ENDIF
        DFCTGT = DFCTGT + XX(4,NDFDIM+2)
        IF (ABS(DFCTGT).GT.1.E+08) THEN
           NDFERR=10
           RETURN
        ENDIF        
        DFSTHE = 1. / SQRT (1. + DFCTGT**2)
        DFPMS(1)  = DFPMS(1) + XX(6,NDFDIM+2)
        DO M=7,NDFDIM,2
          DFPMS(M-5)  = DFPMS(M-5) + XX(M,NDFDIM+2)
          DFPMS(M-4)  = DFPMS(M-4) + XX(M+1,NDFDIM+2)
        ENDDO
        DFPY(NDF1) = SIN (DFPHI) * DFSTHE
        DFPX(NDF1) = COS (DFPHI) * DFSTHE
        DFPZ(NDF1) = DFCTGT * DFSTHE

        IF (ABS (DFZ(NDF1)).GT.CDFZMA . OR .
     +      ABS (DFZ(NDFL)).GT.CDFZMA) THEN

C--------  TRACK OUTSIDE VISIBLE VOLUME

          NDFERR = 5
          CALL INERR (431)
          RETURN
        ENDIF

C--------  NEW CHISQ -  KAPITZA(24)
C--------  NDFMCH IS THE WIRE WITH THE BIGGEST CHISQ (=DFMCH)

        DFCHIN = 0.
        DFMCH = 0.
        CALL VZERO(CH2A,MXHIT)
        CALL VZERO(CH2B,MXHIT)
        N = NDF1
        
C	IT_LOOP=0     !<COM 6-11

        DO WHILE (N.GT.0)
          IF (LDFL(N).GT.0)  THEN
            CH2A(N) = - DFCH(N)
            DO I=1,NDFDIM
               CH2B(N) = CH2B(N) + XX(I,NDFDIM+2) * DFA(I,N)
            ENDDO
            CH2 = CH2A(N) + CH2B(N)
            CH2 = CH2**2 / DFE(N)
            DFCHIN = DFCHIN + CH2
            IF (N.EQ.NDF1 . OR . N.EQ.NDFL)  CH2 = CH2 * CMAX1L

C	    if(CH2.GE.25) IT_LOOP = IT_LOOP + 1  !<COM 6-11

            IF (CH2.GE.DFMCH)  THEN
              DFMCH = CH2
              NDFMCH = N
            ENDIF
          ENDIF
          N = NDF(N)
        ENDDO

C-------  MULT. SCATT. CONTRIBUTION TO CHISQ - CF NIM(55)

        DFCMS2 = 0.
        DO M=7,NDFDIM
          DFCMS2 = DFCMS2 + DFPMS(M-5)**2 * DFEMS(M-5)
        ENDDO
        DELTA=0.05*NPRHITS
        IF (DFCHIN+DFCMS2 .GT. DFCHI2+DFCMSO+DELTA) THEN

C-------  PREDICTED CHISQ WORSE THAN CHISQ OF THIS ITERATION

          CALL INERR (413)
          NDFERR = 3
          RETURN
        ENDIF

C    CHECK IF THE ITERATION PROCEDURE HAS CONVERGED

        IF (DFCHI2+DFCMSO-DFCHIN-DFCMS2 .LE. CUTCHI) THEN
          RETURN
        ENDIF
      ENDDO

C-------  TOO MANY ITERATIONS

      CALL INERR (414)
      NDFERR = 6
      RETURN

      END
C
C*DK DFJOIN        !< COM6-11 (METTERE  DFJOIN)
C=======================================================================
C
      SUBROUTINE DFJOIN(SUPERSTATUS) 
C
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : This routine scans all track pairs to identify
C-                         cases in which a track has been split in 2
C-                         (or more) stumps by the old ARGUS pattern 
C-                         routines.
C-
C-    Author: 
C     =======
C     G.Venanzoni 29-9-97		
C	
C----------------------------------------------------------------------
C
C------ Global Declarations -------------------------------------------
C
$$implicit
C
C------ Include Files -------------------------------------------------
C
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$INC:JOBSTA.INC'
$$include 'K$INC:OFERCO.INC'
$$INCLUDE 'K$ITRK:DTFS.INC'
$$INCLUDE 'K$ITRK:STUMPCOM.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
C
C------ External Declarations ------------------------------------------
C
C------ Local Declarations ---------------------------------------------
	integer SUPERSTATUS,STATUS
	integer COMSTATUS,IS,NDUPL,NSTRNG,ICOP
	integer TRK1,TRK2,VCOP(5),FCOP,NCOPCON
	integer V_FCOP(5),V_NCOP(5),I
	integer A_NCOP(5,5),ISTR,JSTR
	integer NSLD,NSLD_ICH,S_NCOP,S_VCOP(5)
	logical SFL(5),DUPFL,LFLG
	real pi
	DATA pi /3.1415/


C------ Start of code -------------------------------------------------
CStart with success
	SUPERSTATUS=OFSUCC
	call DFJSTUMP(COMSTATUS) !Fill STUMPCOM Common Block
	if (COMSTATUS.ne.OFSUCC) NCOP =0
	if(NCOP.eq.0) goto 900 

	do IS=1,5
	 SFL(IS)=.true.
	enddo
	NDUPL = 0
	NSTRNG = 0
	do 100  ICOP =1, NCOP
	  TRK1 = FIRSTUMP(ICOP)  
	  TRK2 = SECSTUMP(ICOP)
  	  if (FHIT(ICOP).eq.1) then !icop is broken on FIRST HIT
	    DUPFL = FHIT(ICOP).eq.1.and.LASTHIT(TRK1).eq.0
     & .and.LASTHIT(TRK2).eq.0 !flag on duplet
  	    if(DUPFL) then  ! icop is a DUBLET
	      NDUPL = NDUPL + 1	  
	      call DFJMRG(TRK1,TRK2,STATUS)
	      goto 100
 	    else   ! icop is a point of a TRIPLET or more
	      NSTRNG = NSTRNG + 1
	      LFLG = .true.	  
	      call DFJTRP(LFLG,TRK1,TRK2,VCOP,FCOP,NCOPCON)
	      V_FCOP(NSTRNG)=FCOP		
	      V_NCOP(NSTRNG)=NCOPCON		
	      do I=1,NCOPCON
	        A_NCOP(NSTRNG,I) =VCOP(I)
	      enddo
	      goto 100
	    endif 
	  else ! icop is broken on LAST HIT
 	    DUPFL = LHIT(ICOP).eq.1.and.FIRSTHIT(TRK1).eq.0
     & .and.FIRSTHIT(TRK2).eq.0 !flag on duplet
	    if(DUPFL) then
	      NDUPL = NDUPL + 1	  
	      call DFJMRG(TRK1,TRK2,STATUS)
	      goto 100
	    else ! icop is a point of a TRIPLET or more
	      NSTRNG = NSTRNG + 1
	      LFLG = .false.	  
	      call DFJTRP(LFLG,TRK1,TRK2,VCOP,FCOP,NCOPCON) 
	      V_FCOP(NSTRNG)=FCOP		
	      V_NCOP(NSTRNG)=NCOPCON		
	      do I=1,NCOPCON
	        A_NCOP(NSTRNG,I) =VCOP(I)
	      enddo
	      goto 100
	    endif
	  endif
 100	continue	  
	
CLook how many different configurations:

	if(NSTRNG.le.1) goto 200
	do 170 ISTR = 1,NSTRNG-1
	 if(.not.SFL(ISTR)) goto 170
	  do JSTR = ISTR+1,NSTRNG 
	    if(V_FCOP(ISTR).eq.V_FCOP(JSTR)) SFL(JSTR) = .false.
	  enddo  	     
 170	continue

C  ncop = nsing + ntrip..

 200	continue
	NSLD = 0
	do ISTR =1,NSTRNG
	  if (SFL(ISTR)) then
	    NSLD_ICH = NCOPCON
	    NSLD = NSLD + NSLD_ICH  
	  endif
	enddo   
	if (NCOP.ne.NDUPL+NSLD) then
	    print*, 'ERROR in calculation NCOP !!!!'
	endif

	do ISTR =1,NSTRNG
	  if (SFL(ISTR)) then	
	    S_NCOP=V_NCOP(ISTR)    
	    do I=1,S_NCOP
	      S_VCOP(I)=A_NCOP(ISTR,I)   
	    enddo  
	    call DFJSTR(ISTR,S_NCOP,S_VCOP)
	  endif 
	enddo
	goto 990

 900	SUPERSTATUS=OFFAIL
 990  continue		
      return
      end

C=======================================================================
C
	SUBROUTINE DFJTRP(LFLG,TRK1,TRK2,VCOP,FCOP,NCOPCON)
C
C=======================================================================
C
C	Description:
C	============
C
C
C 	Author:
C 	=======
C	G.Venanzoni 22-9-97
C------------------------------------------------------------------------
C----------------------------------------------------------------------
C
C------ Global Declarations -------------------------------------------
C
$$IMPLICIT
C
C
C------ Include Files -------------------------------------------------
C
$$INCLUDE 'K$INC:ERLEVL.INC'
$$include 'k$inc:oferco.inc'
$$INCLUDE 'K$ITRK:STUMPCOM.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
C
C------ External Declaration  --------------------------------------------
C
	integer GETCOP	
C
C------ Local Declarations -------------------------------------------
C
	logical LFLG,LFLG_FIRST
	integer TRK,TRK1,TRK2,NTRK,IT,TRKNUM(6)
	integer COPARRAY(5),HIT,TRK_OLD,COPMIN
	integer ICOP,NCOPCON,FCOP,VCOP(5)
C
C----- Start of Code --------------------------------------------------
C
	LFLG_FIRST = LFLG
	TRK = TRK1
	NTRK= 1 
	IT = 1
	TRKNUM(1) = TRK1
	COPARRAY(1)= GETCOP(TRK1,TRK2)
	if (COPARRAY(1).eq.-1) then
	  call ERLOGR('DFJTRP',ERWARN,0,0,'Cannot find COP')
	  goto 900
	endif	
 20	continue
	if (LFLG) then
	  HIT = LASTHIT(TRK)
	else
	  HIT = FIRSTHIT(TRK)
	endif	 
	do while (HIT.eq.1)  		
	  IT = IT + 1 ! # of trks connected with FIRSTUMP (included the first)
	  if(LFLG) then
	    TRK_OLD = TRK
 	    TRK = COMP_L(TRK)
	    TRKNUM(IT) = TRK	
	    COPARRAY(IT) = GETCOP(TRK_OLD,TRK)
	    if(COPARRAY(IT).eq.-1) then
	      call ERLOGR('DFJTRP',ERWARN,0,0,'Cannot find COP')
	      goto 900
	    endif			
	    HIT = FIRSTHIT(TRK)
	    LFLG = .false.
	  else 
	    TRK_OLD = TRK
	    TRK = COMP_F(TRK)
	    TRKNUM(IT) = TRK	
	    COPARRAY(IT) = GETCOP(TRK_OLD,TRK)
	    if(COPARRAY(IT).eq.-1) then
	      call ERLOGR('DFJTRP',ERWARN,0,0,'Cannot find COP')
	      goto 900
	    endif	
	    HIT = LASTHIT(TRK)
	    LFLG = .true.	    
	  endif 
    	enddo
	if(NTRK.eq.2) then
	  goto 100  	   	
	else
	  NTRK=2	
	  TRK = TRK2
	  LFLG = LFLG_FIRST			
	  goto 20 
	endif
	
 100	continue
	TRKNUM(IT+1) = TRK2
	COPMIN=10
	do ICOP=1,IT
	  if(COPARRAY(ICOP).lt.COPMIN) then
	    COPMIN=COPARRAY(ICOP)
	  endif	
	enddo
	FCOP=COPMIN      !NUMBER OF FIRST COP				
	NCOPCON=IT      !NUMBER OF COPS CONNECTED 
	do ICOP=1,NCOPCON
	  VCOP(ICOP)=COPARRAY(ICOP)
	enddo
	call VZERO(COPARRAY,NCOPCON)	
 900	return
	end

C================================================================
C
	Integer Function GETCOP(TRK1,TRK2)
C
C================================================================
C
C	Description:
C	============
CIT retrives the Number of COP connecting TRK1 AND TRK2
C
C	Author:
C	=======
C	G.Venanzoni 22-9
C
C---------------------------------------------------------------------
C------ Global Declarations -------------------------------------------
C
$$IMPLICIT
C
C
C------ Include Files -------------------------------------------------
C
$$INCLUDE 'K$INC:ERLEVL.INC'
$$include 'k$inc:oferco.inc'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:STUMPCOM.INC'
C
C------ External Declaration  --------------------------------------------
c

C------ Local Declarations -------------------------------------------
C
	integer IC,TRK1,TRK2

C----- Start of Code --------------------------------------------------
C
	GETCOP=-1
	do IC=1,NCOP
	  if((FIRSTUMP(IC).eq.TRK1.and.SECSTUMP(IC).eq.TRK2).or.
     &  (FIRSTUMP(IC).eq.TRK2.and.SECSTUMP(IC).eq.TRK1)) then
	    GETCOP=IC
	    goto 900
          endif		
	enddo

 900 	continue
	return
	end


C===================================================================
C
	SUBROUTINE DFJSTR(ISTRING,S_NCOP,S_VCOP)
C				
C===================================================================
C
C	Description:
C	============
CIT breaks String #ISTRING according to the Quality Factor of each COP
C
C	Author:
C	=======
C	G.Venanzoni 23-9
C
C------ Global Declarations -------------------------------------------
C
$$IMPLICIT
C
C
C------ Include Files -------------------------------------------------
C
$$INCLUDE 'K$INC:ERLEVL.INC'
$$include 'k$inc:oferco.inc'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:STUMPCOM.INC'    
C
C------ External Declaration  --------------------------------------------
c

C------ Local Declarations -------------------------------------------
C
	integer ICOP,S_NCOP,S_VCOP(5),SNCOP,ISTRING
	integer BESTICOP,TRK1,TRK2,TRK1_OLD,TRK2_OLD
	real QF(5),QFGI,QF_OLD
	integer IDCOP_OLD,STATUS

C----- Start of Code --------------------------------------------------
C
	do ICOP=1,S_NCOP
	  QF(ICOP)=QF0(S_VCOP(ICOP))+QF1(S_VCOP(ICOP))+QF2(S_VCOP(ICOP))+
     + QF3(S_VCOP(ICOP))+QF4(S_VCOP(ICOP)) !FOR THE MOMENT THE SIMPLEST COMB.
	enddo

Cget the best QF and start to connect the corrispective  ICOP 	
	SNCOP = S_NCOP
	 do while(SNCOP.gt.0) 
	   QFGI =0.
	   do 20 ICOP =1,SNCOP
	    if(QF(ICOP).gt.QFGI) then
	     BESTICOP = ICOP
	     QFGI = QF(ICOP)
	    endif
 20 	   continue
	TRK1=FIRSTUMP(S_VCOP(BESTICOP))
	TRK2=SECSTUMP(S_VCOP(BESTICOP))
	TRK1_OLD = 0
	TRK2_OLD = 0
	if (TRK1.eq.TRK1_OLD.or.TRK1.eq.TRK2_OLD.or.
     & 	TRK2.eq.TRK1_OLD.or.TRK1.eq.TRK2_OLD) goto 100
	  call DFJMRG(TRK1,TRK2,STATUS)
	TRK1_OLD = TRK1
	TRK2_OLD = TRK2
 100	continue
	QF_OLD = QF(NCOP)      !Store Q.F. 
	IDCOP_OLD = S_VCOP(NCOP) !Store Identity of COP
	QF(NCOP) = QF(BESTICOP)
	S_VCOP(NCOP) = S_VCOP(BESTICOP)
	QF(BESTICOP)=QF_OLD
	S_VCOP(BESTICOP)= IDCOP_OLD
	SNCOP = SNCOP-1
	enddo
 900  continue

      RETURN
      END
C=======================================================================
C
	SUBROUTINE DFJMRG(TRK1,TRK2,STATUS)

C=======================================================================
C
C	DESCRIPTION:
C      	===========
CIt makes the merging of the two DPRS banks, creating the # BIGGGEST+1 
Cnew DPRS Bank
C
C	Author:
C	=======
C	G.Venanzoni 23-9-97
C
C------ Global declaration ---------------------------------------------
c
$$implicit
c
c------ Include Files --------------------------------------------------
c
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$INC:ERLEVL.INC'
$$include 'K$INC:OFERCO.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$include 'K$ITRK:DHRE.INC'
$$include 'K$ITRK:DPRS.INC'
$$include 'K$ITRK:DTFS.INC'
$$include 'K$ITRK:STUMPCOM.INC'
c
c------ External Declaration -------------------------------------------
c	
	integer BIGEST,BTYMKG,BLOCAT,GETCOP
	real 	GETLENG
c------ Local Declaration ----------------------------------------------
c
	integer JOIN_NUM,ISTAT,STATUS
	integer DPRSBNK,BNKSIZ,IND_DP,INDDAT_DP
	integer ISTAT_DTF1,ISTAT_DTF2,IND_DTF1,IND_DTF2
	integer TRK1,TRK2,INDDAT_DTF1,INDDAT_DTF2
	integer POINT_TR1,POINT_TR2,POINT_FIRSTRK,POINT_SECTRK	
	integer FTRK,STRK,NHITPOS_FTRK,NHITNEG_FTRK,NHIT_FTRK
	integer NHITPOS_STRK,NHITNEG_STRK,NHIT_STRK,NHITD
	integer I,IWIRE,W_PREV,ICOP
	integer IND_DHR,INDDAT_DHR,DHRECO
	real 	XCOOR_HIT1,YCOOR_HIT1,XCOOR_HIT2,YCOOR_HIT2
	real 	DISTXY1,DISTXY2,F1,F2,COTFIRST,SINFIRST
	real 	COSFIRST,COTSEC,SINSEC,COSSEC,COSTHETA
	real 	ZCOP,SCOP,PI,DRIFT_P
	data 	pi /3.1415/
	logical	DFLG,FH
        character*80 BNKTYP
        data BNKTYP/'2I4,9R4,2I4,R4,2I4,2R4,I4,XXX(I4,R4)'/

	real  ZCOOR_HIT1,ZCOOR_HIT2,DISTR1,DISTR2  !for joined trk close to IR

c
C------ Start of code --------------------------------------------------
C
CSTART with success
	STATUS = OFSUCC
c

C----- Take the BIGGEST number of DPRS ---------------------------------
C
	ISTAT = BIGEST (IW,'DPRS',JOIN_NUM)
	if (ISTAT.ne.YESUCC) then
	  call ERLOGR ('DFJOIN',ERWARN,0,0,'Cannot find DPRS')
	   goto 990
	endif

c------ Locate The two bank --------------------------------------------
c
	ISTAT = BLOCAT (IW,'DTFS',TRK1,IND_DTF1,INDDAT_DTF1)
	if (ISTAT.ne.YESUCC) then
          call ERLOGR ('DPRMERGE',ERWARN,0,0,'Cannot find DTFS')
	  goto 990
        endif
	ISTAT = BLOCAT (IW,'DTFS',TRK2,IND_DTF2,INDDAT_DTF2)
	if (ISTAT.ne.YESUCC) then
          call ERLOGR ('DPRMERGE',ERWARN,0,0,'Cannot find DTFS')
	  goto 990
        endif
		 
C----- Locate also DHRE bank for reversing the measured drift time ------
c
	ISTAT = BLOCAT(IW,'DHRE',2,IND_DHR,INDDAT_DHR)
	if (ISTAT.ne.YESUCC) then
          call ERLOGR ('DPRMERGE',ERWARN,0,0,'Cannot locate DHRE')
	  goto 990
        endif
	DHRECO=IW(INDDAT_DHR+DHRNCO)
	INDDAT_DHR=INDDAT_DHR+IW(INDDAT_DHR+DHRHDS)

C Get COP Number:
	ICOP= GETCOP(TRK1,TRK2)

	POINT_TR1=INDDAT_DTF1+IW(INDDAT_DTF1+DTFHDS) 
	POINT_TR2=INDDAT_DTF2+IW(INDDAT_DTF2+DTFHDS) 

	if(FHIT(ICOP).eq.1) then !ICOP is broken in the First hit 
	  FH=.true.
	  XCOOR_HIT1= RW(POINT_TR1+DTFXLP)
	  YCOOR_HIT1= RW(POINT_TR1+DTFYLP)

	  XCOOR_HIT2= RW(POINT_TR2+DTFXLP)
	  YCOOR_HIT2= RW(POINT_TR2+DTFYLP)
	else !ICOP is broken in the Last hit
	  FH=.false.
	  XCOOR_HIT1= RW(POINT_TR1+DTFXCO)
	  YCOOR_HIT1= RW(POINT_TR1+DTFYCO)
	  ZCOOR_HIT1= RW(POINT_TR1+DTFZCO)


	  XCOOR_HIT2= RW(POINT_TR2+DTFXCO)
	  YCOOR_HIT2= RW(POINT_TR2+DTFYCO)
	  ZCOOR_HIT2= RW(POINT_TR2+DTFZCO)
	endif	
	DISTXY1=sqrt(XCOOR_HIT1**2+YCOOR_HIT1**2)
	DISTXY2=sqrt(XCOOR_HIT2**2+YCOOR_HIT2**2)

C! tracks with endpoints close to the IR- compare tridim r:
	if(DISTXY1.lt.50.and.DISTXY2.lt.50) then
	  DISTR1 = sqrt(DISTXY1**2+ZCOOR_HIT1**2)
	  DISTR2 = sqrt(DISTXY2**2+ZCOOR_HIT2**2)
	  DFLG =DISTR1 .lt.  DISTR2 
	else			
 	  DFLG = DISTXY1.lt.DISTXY2	
	endif
	if (DFLG) then !lastpoint of trk1 is the first hit !!!
	  POINT_FIRSTRK= POINT_TR1 
	  POINT_SECTRK = POINT_TR2 
	  FTRK=TRK1
	  STRK=TRK2
	else !lastpoint of trk2 is the first hit !!!
	  POINT_FIRSTRK= POINT_TR2 
	  POINT_SECTRK = POINT_TR1 				
	  FTRK=TRK2
	  STRK=TRK1
	endif

	NHITPOS_FTRK=IW(POINT_FIRSTRK+DTFNHF)/10000	
	NHITNEG_FTRK=mod(IW(POINT_FIRSTRK+DTFNHF),10000)		
	NHIT_FTRK=NHITPOS_FTRK+NHITNEG_FTRK

	NHITPOS_STRK=IW(POINT_SECTRK+DTFNHF)/10000	
	NHITNEG_STRK=mod(IW(POINT_SECTRK+DTFNHF),10000)		
	NHIT_STRK=NHITPOS_STRK+NHITNEG_STRK
	NHITD=NHIT_FTRK+NHIT_STRK
	F1=float(NHIT_FTRK)/NHITD	
	F2=float(NHIT_STRK)/NHITD	

C----- Create the 2nd version of DPRS -----------------------------------
c
C  Now make the corresponding DPRS bank, and fill the header

        WRITE (BNKTYP(27:29),'(I3)') NHITD
	STATUS = BTYMKG(IW,'DPRS',JOIN_NUM+1,
     & BNKTYP,BNKSIZ,IND_DP,INDDAT_DP)
      	if (STATUS.NE.YESUCC) then
          CALL ERLOGR('DFJOIN',ERWARN,0,0,
     +                    'Error creating bank DPRS')
	  goto 990
	endif 	

	BNKS(ICOP)=JOIN_NUM+1
      if(FH) then
	
C       Fill bank DPRS first (for the first HIT)
C       ====================
        IW(INDDAT_DP+DPRHDS) = 2
      	IW(INDDAT_DP+DPRVRN) = 2
      	INDDAT_DP = INDDAT_DP + IW(INDDAT_DP+DPRHDS)

	RW(INDDAT_DP+DPRXCO) = RW(POINT_FIRSTRK+DTFXLP) !	
	RW(INDDAT_DP+DPRYCO) = RW(POINT_FIRSTRK+DTFYLP)	!
	RW(INDDAT_DP+DPRZCO) = RW(POINT_FIRSTRK+DTFZLP)	!

	RW(INDDAT_DP+DPRXLS) = RW(POINT_SECTRK+DTFXLP)	
	RW(INDDAT_DP+DPRYLS) = RW(POINT_SECTRK+DTFYLP)	
	RW(INDDAT_DP+DPRZLS) = RW(POINT_SECTRK+DTFZLP)	

	RW(INDDAT_DP+DPRCUR) = -RW(POINT_FIRSTRK+DTFCUR)*F1+
     & RW(POINT_SECTRK+DTFCUR)*F2 ! invert first track sign
	RW(INDDAT_DP+DPRPHI) = RW(POINT_FIRSTRK+DTFPLP) - PI !F(-PI;PI) for FHIT
	RW(INDDAT_DP+DPRCTT) = -RW(POINT_FIRSTRK+DTFTLP)*F1 +
     & RW(POINT_SECTRK+DTFCTT)*F2	
	IW(INDDAT_DP+DPRPOS) = NHITPOS_FTRK+NHITPOS_STRK !
	IW(INDDAT_DP+DPRNEG) = NHITNEG_FTRK+NHITNEG_STRK !
	RW(INDDAT_DP+DPRQUA) = 0.
 	IW(INDDAT_DP+DPRPOK) = 3
	IW(INDDAT_DP+DPRLRG) = 0
	RW(INDDAT_DP+DPRPHF) = 0. 
	RW(INDDAT_DP+DPRPHL) = 0.
	IW(INDDAT_DP+DPRCEN) = 0
	INDDAT_DP=INDDAT_DP+16 !point to the hits block
	
C Now First TRK
	do I=1,NHIT_FTRK-1    !I in the DPRS sense
	  IWIRE=IW(POINT_FIRSTRK+DTFFHA+NHIT_FTRK-I)
	  IW(INDDAT_DP+DPRLWI*(I-1)+DPRIWI)=IWIRE
	  W_PREV=IW(POINT_FIRSTRK+DTFFHA+NHIT_FTRK-I-1) !take prec. one
	  RW(INDDAT_DP+DPRLWI*(I-1)+DPRWTR)=GETLENG(FTRK,W_PREV,STATUS)
	  if(STATUS.ne.OFSUCC) then
            CALL ERLOGR('DFJOIN',ERWARN,0,0,
     +                    'Error filling DPRS')
	    goto 990
	  endif 	
C reverse drift distance sign:
	  DRIFT_P=RW(INDDAT_DHR+DHRECO*(IWIRE-1)+DHRRAD)
	  RW(INDDAT_DHR+DHRECO*(IWIRE-1)+DHRRAD)=-DRIFT_P
	enddo			 

C Now the COP (wire position:NHIT_FTRK):
C For the moment the simple relation:s=dz/cos(theta)

	  IW(INDDAT_DP+DPRLWI*(NHIT_FTRK-1)+DPRIWI)=
     &    IW(POINT_FIRSTRK+DTFFHA)
	  DRIFT_P=RW(INDDAT_DHR+DHRECO*(IW(POINT_FIRSTRK+DTFFHA)-1)
     &  +DHRRAD)
          RW(INDDAT_DHR+DHRECO*(IW(POINT_FIRSTRK+DTFFHA)-1)+
     &  +DHRRAD)=-DRIFT_P
	
	  ZCOP=RW(POINT_FIRSTRK+DTFZCO)-RW(POINT_SECTRK+ 
     &   DTFZCO)
	  COTFIRST = RW(POINT_FIRSTRK+DTFCTT)	  
	  SINFIRST = SQRT(1./(1.+COTFIRST**2))
	  COSFIRST = SINFIRST*COTFIRST 

	  COTSEC = RW(POINT_SECTRK+DTFCTT)	  
	  SINSEC = SQRT(1./(1.+COTSEC**2))
	  COSSEC = SINSEC*COTSEC 

	  COSTHETA=-COSFIRST*F1+COSSEC*F2
	  if(COSTHETA.gt.1.) COSTHETA=1.
	  if(COSTHETA.lt.-1.) COSTHETA=-1.
	  SCOP=ABS(ZCOP/COSTHETA*SINFIRST) !2D, AS IN DFINIT
	  RW(INDDAT_DP+DPRLWI*(NHIT_FTRK-1)+DPRWTR)=SCOP

C Now Second TRK
	do I=NHIT_FTRK+1,NHITD
 	  IWIRE=IW(POINT_SECTRK+DTFFHA+(I-NHIT_FTRK)-1)
	  IW(INDDAT_DP+DPRLWI*(I-1)+DPRIWI)=IWIRE	
	  RW(INDDAT_DP+DPRLWI*(I-1)+DPRWTR)=GETLENG(STRK,IWIRE,STATUS)
	  if(STATUS.ne.OFSUCC) then
            CALL ERLOGR('DFJOIN',ERWARN,0,0,
     +                    'Error filling DPRS')
	    goto 990
	  endif 		  
	enddo

      else

C       Fill bank DPRS first (for the LAST HIT)
C       ====================
        IW(INDDAT_DP+DPRHDS) = 2
      	IW(INDDAT_DP+DPRVRN) = 2
      	INDDAT_DP = INDDAT_DP + IW(INDDAT_DP+DPRHDS)

	RW(INDDAT_DP+DPRXCO) = RW(POINT_FIRSTRK+DTFXCO) !	
	RW(INDDAT_DP+DPRYCO) = RW(POINT_FIRSTRK+DTFYCO)	!
	RW(INDDAT_DP+DPRZCO) = RW(POINT_FIRSTRK+DTFZCO)	!

	RW(INDDAT_DP+DPRXLS) = RW(POINT_SECTRK+DTFXCO)	
	RW(INDDAT_DP+DPRYLS) = RW(POINT_SECTRK+DTFYCO)	
	RW(INDDAT_DP+DPRZLS) = RW(POINT_SECTRK+DTFZCO)	

	RW(INDDAT_DP+DPRCUR) = +RW(POINT_FIRSTRK+DTFCUR)*F1-
     & RW(POINT_SECTRK+DTFCUR)*F2 ! invert the sign of the first trk
	RW(INDDAT_DP+DPRPHI) = RW(POINT_FIRSTRK+DTFPHI)
	RW(INDDAT_DP+DPRCTT) = RW(POINT_FIRSTRK+DTFCTT)*F1 -
     & RW(POINT_SECTRK+DTFTLP)*F2	
	IW(INDDAT_DP+DPRPOS) = NHITPOS_FTRK+NHITPOS_STRK 
	IW(INDDAT_DP+DPRNEG) = NHITNEG_FTRK+NHITNEG_STRK 
	RW(INDDAT_DP+DPRQUA) = 0.
 	IW(INDDAT_DP+DPRPOK) = 3
	IW(INDDAT_DP+DPRLRG) = 0
	RW(INDDAT_DP+DPRPHF) = 0. 
	RW(INDDAT_DP+DPRPHL) = 0.
	IW(INDDAT_DP+DPRCEN) = 0
	INDDAT_DP=INDDAT_DP+16 !point to the hits block
	

C Now First TRK                !I is in the  DPRS direction
	do I=1,NHIT_FTRK-1
 	  IWIRE=IW(POINT_FIRSTRK+DTFFHA+I-1)
	  IW(INDDAT_DP+DPRLWI*(I-1)+DPRIWI)=IWIRE	
	  RW(INDDAT_DP+DPRLWI*(I-1)+DPRWTR)=GETLENG(FTRK,IWIRE,STATUS)
	  if(STATUS.ne.OFSUCC) then
            CALL ERLOGR('DFJOIN',ERWARN,0,0,
     +                    'Error filling DPRS')
	    goto 990
	  endif 	
	enddo


C Now the COP (wire position:NHIT_FTRK)
C For the moment the simple relation:s=dz/cos(theta)

	  ZCOP=RW(POINT_FIRSTRK+DTFZLP)-RW(POINT_SECTRK+DTFZLP)
	  IW(INDDAT_DP+DPRLWI*(NHIT_FTRK-1)+DPRIWI)=
     &    IW(POINT_FIRSTRK+DTFFHA+NHIT_FTRK-1)

	  COTFIRST = RW(POINT_FIRSTRK+DTFTLP)	  
	  SINFIRST = SQRT(1./(1.+COTFIRST**2))
	  COSFIRST = SINFIRST*COTFIRST 

	  COTSEC = RW(POINT_SECTRK+DTFTLP)	  
	  SINSEC = SQRT(1./(1.+COTSEC**2))
	  COSSEC = SINSEC*COTSEC 

	  COSTHETA=COSFIRST*F1-COSSEC*F2
	  if(COSTHETA.gt.1.) COSTHETA=1.
	  if(COSTHETA.lt.-1.) COSTHETA=-1.
	  SCOP=ABS(ZCOP/COSTHETA*SINFIRST) !2D, as in DFINIT
	  RW(INDDAT_DP+DPRLWI*(NHIT_FTRK-1)+DPRWTR)=SCOP

C Now second TRK
	do I=NHIT_FTRK+1,NHITD-1
	  IWIRE=IW(POINT_SECTRK+DTFFHA+NHITD-I)
	  IW(INDDAT_DP+DPRLWI*(I-1)+DPRIWI)=IWIRE
	  W_PREV=IW(POINT_SECTRK+DTFFHA+NHITD-I-1) !take prec. one
	  RW(INDDAT_DP+DPRLWI*(I-1)+DPRWTR)=GETLENG(STRK,W_PREV,STATUS)
	  if(STATUS.ne.OFSUCC) then
            CALL ERLOGR('DFJOIN',ERWARN,0,0,
     +                    'Error filling DPRS')
	    goto 990
	  endif 	
C reverse drift distance sign:
	  DRIFT_P=RW(INDDAT_DHR+DHRECO*(IWIRE-1)+DHRRAD)
	  RW(INDDAT_DHR+DHRECO*(IWIRE-1)+DHRRAD)=-DRIFT_P
	enddo		  


C Now Last HIT
C I=NHIT
	IW(INDDAT_DP+DPRLWI*(NHITD-1)+DPRIWI)=
     & IW(POINT_SECTRK+DTFFHA)	
	RW(INDDAT_DP+DPRLWI*(NHITD-1)+DPRWTR)=0.
	DRIFT_P=RW(INDDAT_DHR+DHRECO*(IW(POINT_SECTRK+DTFFHA)-1)
     & +DHRRAD)
	RW(INDDAT_DHR+DHRECO*(IW(POINT_SECTRK+DTFFHA)-1)+
     &  DHRRAD)=-DRIFT_P
      endif	


 900	continue
	goto 999

 990 	continue 
	STATUS=OFFAIL

 999  	return
	end

C=================================================================
C
	REAL FUNCTION GETLENG(TRK,IWIRE,STATUS)
C
C=================================================================
C
C	Description:
C	============
CIt retrives step lengh of the corresponding iwire
C
C	Author:
C	=======
C	G.Venanzoni 26-9-97
C
C------ Global Declarations -------------------------------------------
C
$$IMPLICIT
C
C
C------ Include Files -------------------------------------------------
C
$$INCLUDE 'K$INC:ERLEVL.INC'
$$include 'k$inc:oferco.inc'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:STUMPCOM.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'
C
C------ External Declaration  --------------------------------------------
c
C------ Local Declarations -------------------------------------------
C
	integer STATUS,KK,TRK,IWIRE
C----- Start of Code --------------------------------------------------
C
	status=ofsucc
	  do 100 kk=1,mxhit
	    if(KDFS(TRK,KK).eq.IWIRE) then
	      GETLENG=DFSS(TRK,KK)
	      goto 999
	    endif	
 100	continue
			
 900	continue
	STATUS=OFFAIL

 999 	return
	end
C=======================================================================
C
      SUBROUTINE DFJSTUMP(COMSTATUS)

C----------------------------------------------------------------------
C IT scan all the track pairs  to identify cases in which a track has been 
C split in 2 (or more) stumps by the old ARGUS pattern routines.
C It fills the COPCOM & TRSCOM COmmon Block (in $TRK_INC:STUMPCOM.INC)
C
C    Author: 
C    =======
C    G.Venanzoni 19-9-97
C----------------------------------------------------------------------
C
C------ Global Declarations -------------------------------------------
C
$$IMPLICIT
C
C
C------ Include Files -------------------------------------------------
C
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$INC:BCS.INC'
$$include 'k$inc:oferco.inc'
$$INCLUDE 'K$ITRK:DTFS.INC'
$$INCLUDE 'K$ITRK:STUMPCOM.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'           <ADD 11-11kink

C
C------ External Declaration  --------------------------------------------
c
      INTEGER BLOCAT,BNEXT,BDATA,BNUMB
      REAL    VDOTN

C------ Local Declarations -------------------------------------------
C
	logical LFHIT,CUTFLG,CUTLLG,MASSFLG
	integer STATUS,STATUS_DTFS,IND,JND,INDTFS,JNDTFS
	integer COMSTATUS,NHITP
	real VXFTRKI,VYFTRKI,VZFTRKI,CURVI,CHARGI
	real VXFTRKJ,VYFTRKJ,VZFTRKJ,CURVJ,CHARGJ
	real VXLTRKI,VYLTRKI,VZLTRKI
	real VXLTRKJ,VYLTRKJ,VZLTRKJ
	real DFTIJXY,DLTIJXY,RCOOI(3),COTI,PHII,SINTHI,TNGI(3)
	real RCOOJ(3),COTJ,PHIJ,SINTHJ,TNGJ(3),DTIJZ
	real COSX,XANG,RMED(2),ORTI,ORTJ,ORT
	real PTTI,PXTI,PYTI,PZTI,ENI
	real PTTJ,PXTJ,PYTJ,PZTJ,ENJ
	real PIJ2,KLMASS,PI,MPI
	DATA  PI/3.1415/,MPI/139.570/
	
	integer STATUS_PR,IND_PR,INDAT_PR,DPVERI  !<ADD11-11 kink
	integer JND_PR,JNDAT_PR,DPVERJ            !<ADD11-11 kink 
C----- Start of Code --------------------------------------------------
C
C Start with Success
	NCOP=0
C	NTI=0
C	NTJ=0
	COMSTATUS = OFSUCC
	call VZERO(FIRSTUMP,MAXNUMNCOP)		
	call VZERO(SECSTUMP,MAXNUMNCOP)		
	call VZERO(FHIT,MAXNUMNCOP)		
	call VZERO(LHIT,MAXNUMNCOP)		
	call VZERO(BNKS,MAXNUMNCOP) !New entry 10-10		
	call VZERO(NHIT,MAXNUMTRS)
	call VZERO(FIRSTHIT,MAXNUMTRS)
	call VZERO(LASTHIT,MAXNUMTRS)
	call VZERO(COMP_F,MAXNUMTRS)
	call VZERO(COMP_L,MAXNUMTRS)

C  Try to identify ARGUS-splits from Pattern Recognition
	
        STATUS_DTFS = BLOCAT(IW,'DTFS',-1,IND,INDTFS)
	if (STATUS_DTFS .NE. YESUCC) THEN
	  call ERLOGR('DFJSTUMP',ERWARN,0,0,'Cannot find DTFS')
	  goto 900
	endif	

        DO WHILE (STATUS_DTFS.eq.YESUCC.and.IND.GT.0)
          STATUS=BDATA(IW,IND,INDTFS)
          IF (STATUS.NE.YESUCC) GOTO 900     	
       	  INDTFS = INDTFS + IW(INDTFS+DTFHDS)
          STATUS = BNUMB(IW,IND,NTI)

C Store DPRS #vers for kinks ! 
	  STATUS_PR = BLOCAT(IW,'DPRS',NTI,IND_PR,INDAT_PR)	!<ADD11-11 kink
	  if(STATUS_PR.NE.YESUCC) then              !<ADD11-11 kink
	    write(6,*)'Error with join-kink'         !<ADD11-11 kink 
	    GOTO 900	                              !<ADD11-11 kink
	  endif  					!<ADD11-11 kink
	  DPVERI=IW(INDAT_PR+DPRVRN)                     !<ADD11-11 kink 

	  VXFTRKI = RW(INDTFS + DTFXCO)
	  VYFTRKI = RW(INDTFS + DTFYCO)
	  VXLTRKI = RW(INDTFS + DTFXLP)
	  VYLTRKI = RW(INDTFS + DTFYLP)
	  CURVI   = RW(INDTFS + DTFCUR)
	  CHARGI  = sign(1., CURVI)	
	

          STATUS_DTFS = BNEXT(IW,IND,JND)
          IF (STATUS_DTFS.ne.YESUCC) GOTO 900     	
	  DO WHILE (STATUS_DTFS.eq.YESUCC.and.JND.GT.0)
          STATUS = BDATA(IW,JND,JNDTFS)
          IF (STATUS.NE.YESUCC) GOTO 900     	
          JNDTFS = JNDTFS + IW(JNDTFS+DTFHDS)
          STATUS = BNUMB(IW,JND,NTJ)

C Store DPRS #vers for kinks ! 
	  STATUS_PR = BLOCAT(IW,'DPRS',NTJ,JND_PR,JNDAT_PR) !<ADD11-11 kink
	  if(STATUS_PR.NE.YESUCC) then         !<ADD11-11 kink
	    write(6,*)'Error with join-kink' 	!<ADD11-11 kink	
	    GOTO 900	                         !<ADD11-11 kink
	  endif 	                          !<ADD11-11 kink
	  DPVERJ=IW(JNDAT_PR+DPRVRN)               !<ADD11-11 kink   

C Skip kinks !
	  if(dpverj.gt.10 .and.              !<ADD11-11 kink
     + (dpverj .eq. dpveri)) goto 100	       !<ADD11-11 kink

	  VXFTRKJ = RW(JNDTFS +DTFXCO)
	  VYFTRKJ = RW(JNDTFS + DTFYCO)
	  VXLTRKJ = RW(JNDTFS + DTFXLP)
	  VYLTRKJ = RW(JNDTFS + DTFYLP)
	  CURVJ   = RW(JNDTFS + DTFCUR)
	  CHARGJ  = sign(1., CURVJ)	

C**** 0) First the selection on total charge.and.on curvature 

	  if(ABS(CURVI+CURVJ).gt.0.5.or.(CHARGI+CHARGJ).ne.0) goto 100				

***** 1) (x,y)distance
             dftijxy=sqrt((vxftrkJ-vxftrkI)**2 +
     + (vyftrkJ-vyftrkI)**2) 
             dltijxy=sqrt((vxltrkJ-vxltrkI)**2 +
     + (vyltrkJ-vyltrkI)**2) 

	LFHIT = (DFTIJXY.lt.DLTIJXY)
	if(LFHIT) then ! split point is in the  first hit			 
	  RCOOI(1) = RW(INDTFS + DTFXCO)  
	  RCOOI(2) = RW(INDTFS + DTFYCO)
	  RCOOI(3) = RW(INDTFS + DTFZCO)
	  COTI     = RW(INDTFS + DTFCTT)
	  PHII     = RW(INDTFS + DTFPHI)
	  SINTHI   = SQRT(1./(1+COTI**2))
	  TNGI(1)  = SINTHI*COS(PHII)	  
	  TNGI(2)  = SINTHI*SIN(PHII)	  
	  TNGI(3)  = SINTHI*COTI	  

	  PTTI    = 1000./ABS(RW(INDTFS+DTFCUR)) 

	  RCOOJ(1) = RW(JNDTFS + DTFXCO)  
	  RCOOJ(2) = RW(JNDTFS + DTFYCO)
	  RCOOJ(3) = RW(JNDTFS + DTFZCO)
	  COTJ     = RW(JNDTFS + DTFCTT)
	  PHIJ     = RW(JNDTFS + DTFPHI)
	  SINTHJ   = SQRT(1./(1+COTJ**2))
	  TNGJ(1)  = SINTHJ*COS(PHIJ)	  
	  TNGJ(2)  = SINTHJ*SIN(PHIJ)	  
	  TNGJ(3)  = SINTHJ*COTJ	

	  PTTJ     = 1000./ABS(RW(JNDTFS+DTFCUR)) 
	else  			!LAST HIT
	  RCOOI(1) = RW(INDTFS + DTFXLP)  
	  RCOOI(2) = RW(INDTFS + DTFYLP)
	  RCOOI(3) = RW(INDTFS + DTFZLP)
	  COTI     = RW(INDTFS + DTFTLP)
	  PHII     = RW(INDTFS + DTFPLP)
	  SINTHI   = SQRT(1./(1+COTI**2))
	  TNGI(1)  = SINTHI*COS(PHII)	  
	  TNGI(2)  = SINTHI*SIN(PHII)	  
	  TNGI(3)  = SINTHI*COTI	  

	  PTTI     = 1000./ABS(RW(INDTFS+DTFCLP))
	  RCOOJ(1) = RW(JNDTFS + DTFXLP)  
	  RCOOJ(2) = RW(JNDTFS + DTFYLP)
	  RCOOJ(3) = RW(JNDTFS + DTFZLP)
	  COTJ     = RW(JNDTFS + DTFTLP)
	  PHIJ     = RW(JNDTFS + DTFPLP)
	  SINTHJ   = SQRT(1./(1+COTJ**2))
	  TNGJ(1)  = SINTHJ*COS(PHIJ)	  
	  TNGJ(2)  = SINTHJ*SIN(PHIJ)	  
	  TNGJ(3)  = SINTHJ*COTJ	

	  PTTJ     = 1000./ABS(RW(JNDTFS+DTFCLP))
	endif

C***** 2) Z Distance:
	DTIJZ = RCOOJ(3)-RCOOI(3)

C***** 3)angle between <ti,-tj>
	cosx = vdotn(tngi,tngj,3)	
        if(cosx.gt.1.)  cosx=1.
        if(cosx.lt.-1.) cosx=-1.
        xang=(pi-acos(cosx))*180./pi

***** 4) ortogonality w.r.t (x,y)
	    RMED(1) =0.5*(RCOOI(1)+RCOOJ(1))
	    RMED(2) =0.5*(RCOOI(2)+RCOOJ(2))
	    ORTI    = VDOTN(TNGI,RMED,2)				 		           
	    ORTJ    = VDOTN(TNGJ,RMED,2)				 		           
	    ORT     = ABS(ORTI+ORTJ)				

***** 5) invariant mass

 	PXTI = PTTI * COS(PHII) ! Px  PAC
	PYTI = PTTI * SIN(PHII) ! Py  PAC
	PZTI = PTTI * COTI      ! Pz  PAC

	PXTJ = PTTJ * COS(PHIJ) ! Px  PAC
	PYTJ = PTTJ * SIN(PHIJ) ! Py  PAC
	PZTJ = PTTJ * COTJ      ! Pz  PAC
	
	ENI = SQRT(PXTI*PXTI+PYTI*PYTI+PZTI*PZTI+
     & MPI*MPI)
	ENJ = SQRT(PXTJ*PXTJ+PYTJ*PYTJ+PZTJ*PZTJ+
     & MPI*MPI)
	PIJ2 = (PXTI+PXTJ)*(PXTI+PXTJ)+
     & (PYTI+PYTJ)*(PYTI+PYTJ)+(PZTI+PZTJ)*(PZTI+PZTJ) 
	KLMASS = SQRT((ENI+ENJ)*(ENI+ENJ)-PIJ2)
C cut on the i.m. (to be sure)
	MASSFLG =KLMASS.lt.480.or.KLMASS.gt.550.

	CUTFLG = LFHIT.and.(ABS(DTIJZ).lt.20.).and.(DFTIJXY.lt.20.).and.
     + (xang.lt.15.).and.(ort.lt.0.4).and.MASSFLG	
	CUTLLG = (.not.LFHIT).and.(ABS(DTIJZ).lt.20.).and.(DLTIJXY.lt.20.).and.
     + (xang.lt.20.).and.(ort.lt.0.3).and.MASSFLG	

	if (CUTFLG.or.CUTLLG) then ! these tracks are candidate stumps
	  NCOP = NCOP +1   !count the stumps
	  QF0(NCOP)  = ABS(CURVI+CURVJ)/.5
	  NT = NTI		
	  FIRSTUMP(NCOP) = NT
	  NHITP = IW(INDTFS+DTFNHF) 
	  NHIT(NT) = NHITP/10000+MOD(NHITP,10000)
	  NT = NTJ	
	  SECSTUMP(NCOP) = NT
	  NHITP = IW(JNDTFS+DTFNHF) 
	  NHIT(NT) = NHITP/10000+MOD(NHITP,10000)

C	  FIRSTUMP(NCOP) = NTI
C	  NHIT(NTI) = IW(INDTFS+DTFNHF)
C	  SECSTUMP(NCOP) = NTJ
C	  NHIT(NTJ) = IW(JNDTFS+DTFNHF)

	  if (LFHIT) then ! FIRST HIT
	    FHIT(NCOP) = 1  ! ncop is in the first hit
	    QF1(NCOP) = ABS(DTIJZ)/15.
	    QF2(NCOP) = DFTIJXY/30. 
	    QF3(NCOP) = XANG/15. 
	    QF4(NCOP) = ORT/.4
	    NT = NTI	
C 	    FIRSTHIT(NTI) = 1
C	    FIRSTHIT(NTJ) = 1
C	    COMP_F(NTI)  = NTJ
C	    COMP_F(NTJ)  = NTI
 	    FIRSTHIT(NT) = 1
	    COMP_F(NT)  = NTJ
	    NT=NTJ	
	    FIRSTHIT(NT) = 1
	    COMP_F(NT)  = NTI
	  else
	    LHIT(NCOP) = 1  ! ncop is in the last hit 
	    QF1(NCOP) = ABS(DTIJZ)/30.
	    QF2(NCOP) = DLTIJXY/30. 
	    QF3(NCOP) = XANG/30. 
	    QF4(NCOP) = ORT/.4
	    NT = NTI
	    LASTHIT(NT) = 1
	    COMP_L(NT)  = NTJ
	    NT = NTJ
	    LASTHIT(NT) = 1
	    COMP_L(NT)  = NTI
C	    LASTHIT(NTI) = 1
C	    LASTHIT(NTJ) = 1
C	    COMP_L(NTI)  = NTJ
C	    COMP_L(NTJ)  = NTI
	  endif	 
	endif
 100	continue
        STATUS_DTFS = BNEXT(IW,JND,JND)
      	ENDDO
      STATUS_DTFS = BNEXT(IW,IND,IND)
      ENDDO
      goto 990
      
 900  COMSTATUS = OFFAIL
 990  continue		
      return
      end
C
C
C*DK DFKILL
C
C=======================================================================
C
      SUBROUTINE DFKILL (NW)
C
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Mark wire "NW" as rejected during track fit, both  
C-                         in the bank DPRS (by sign reversing) and in the 
C-                         working vectors in /CDFWORK/ (by removing it from
C-                         the chain NDF)
C-                  NOTE : NW is NOT an index in the overall hit banks 
C-                         DHRE,DTHA (which are to be left untouched)
C-                         but in the (smaller) one-track working banks

$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:cdfcut.inc'  
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'C$INC:JOBSTA.INC'
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$ITRK:cdfwork.inc'
	
      integer npass2       !< AGG6-11 
      common /NP/ npass2   !< AGG6-11


      INTEGER NW,N1,N0,NDIFF(MXHIT),TEST,STATUS
      LOGICAL DIFFER

      NDFERR = 0

C-------  ENOUGH WIRES LEFT ?
C-------  THIS TEST MAY FAIL ONLY WHEN CALLED FROM DFREJ; WHEN CALLED 
C-------  FROM DFADD WE REMOVE JUST A HIT PREVIOUSLY ADDED TO THE TRACK 

      IF (TIDST(LDFL(NW)) .LT. 0.) NFITNEG = NFITNEG-1
      IF (TIDST(LDFL(NW)) .GT. 0.) NFITPOS = NFITPOS-1
      IF (NFITNEG+NFITPOS .LE. MIN0(NCUTSTEREO,6)) THEN
        CALL ERLOGR('DFKILL',ERWARN,0,STATUS,
     +      'Too many hits rejected : only 5 hits remain.')
        NDFERR = 8
        RETURN
      ENDIF

C-------  ENOUGH DIFFERENT LAYERS ? 

      N1 = NDF1
      NL_CR = 0
      DO WHILE (N1.GT.0 .AND. NL_CR.LT.2)
        IF (N1.NE.NW) THEN
          DIFFER = .TRUE.
          DO TEST=1,NL_CR
            IF (LDFL(N1) .EQ. NDIFF(TEST)) DIFFER = .FALSE.
          ENDDO
          IF (DIFFER) THEN
            NL_CR = NL_CR + 1
            NDIFF(NL_CR) = LDFL(N1)
          ENDIF
        ENDIF
        N1 = NDF(N1)
      ENDDO
      IF (NL_CR .LT. 2) THEN
        CALL ERLOGR('DFKILL',ERWARN,0,STATUS,
     +      'number of different crossed layer <2')
        NDFERR = 9
        RETURN
      ENDIF

      NDFC = NDFC-1

C-------  MARK THE WIRE IN THE BANK DPRS, BUT CAREFUL: ONLY A POINT
C-------  WHICH WAS ORIGINALLY THERE CAN BE REMOVED. POINTS ADDED BY
C-------  DFADD ARE NOT IN DPRS BY DEFINITION.

      IF (NW .LE. IW(JDPRS+DPRPOS)+IW(JDPRS+DPRNEG))
     .IW(JDPRS1+DPRLWI*(NW-1)+DPRIWI) = - IW(JDPRS1+DPRLWI*(NW-1)+DPRIWI)

C-------  MARK THE WIRE IN THE WORKING AREA

      IF     (NW .EQ. NDF1) THEN

C-------  1ST WIRE REJECTED : SET NDF1 TO THE FIRST POINT NOT YET REJECTED
C-------  AND DECREASE THE DFL STEPS.

        N0=NDF1
        NDF1 = NDF(NW)
        NDF(NW) = 0
        N1 = NDF1
        DO WHILE (N1.GT.0)
          DFL(N1) = DFL(N1)-DFS(NW)
          N1 = NDF(N1)
        ENDDO
        DFCTGT = DFPZ(NDF1) / SQRT (DFPX(NDF1)**2 + DFPY(NDF1)**2)
        DFSTHE = 1. / SQRT (1. + DFCTGT**2)
        DFPHI  = ATAN2 (DFPY(NDF1) , DFPX(NDF1))

        DO WHILE (NDF(NDF1).GT.0 .AND. LDFL(NDF1).EQ.0)
          DFL(NDF(NDF1)) = DFL(NDF1) + DFS(NDF1)
          CALL DFNEXT (NDF1,NDF(NDF1),DFS(NDF1))
          NDF1 = NDF(NDF1)
        ENDDO
        NDFMS(1) = NDF1

      ELSEIF (NW .EQ. NDFL) THEN

C-------  LAST WIRE REJECTED ; DECREASE NUMBER OF STEPS (NDFL)

        N1 = NDF1
        DO WHILE (NDF(N1).NE.NW .AND. NDF(N1).GT.0)
          N1 = NDF(N1)
        ENDDO
        NDFL = N1
        NDF(NDFL) = 0
        NDF(NW) = 0
        DFS(NDFL) = 0.

        N1 = NDFL
        DO WHILE (LDFL(N1).EQ.0 .AND. N1.GE.1)
           IF (MDF(N1).NE.0)  NDFDIM = NDFDIM - 2
           MDF(N1) = 0
           N1 = N1-1
        ENDDO
      ELSE

C-------  REJECTED WIRE IS IN THE MIDDLE; SHORT-CIRCUIT POINTERS "NDF"

        N1 = NDF1
        DO WHILE (NDF(N1).NE.NW .AND. NDF(N1).GT.0)
          N1 = NDF(N1)
        ENDDO
        NDF(N1) = NDF(NW)
        NDF(NW) = 0
        DFS(N1) = DFS(N1)+DFS(NW)
      ENDIF

      IF (npass2.eq.2 .and. LDFMUS.GE.0) THEN
         IF (MDF(NW).NE.0.OR.NW.EQ.N0) THEN
            CALL DFMUSC
         ENDIF
      ENDIF

      RETURN
      END
C      
C*DK DFMUSC
C
C=======================================================================
C
      SUBROUTINE DFMUSC
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : To prepare the trck fit in DFITER for a treatment
C-                         of Multiple Coulomb Scattering. The lateral
C-                         average displacement after a STEP is given by
C-
C-                              STEP        13.6
C-                            -------- * ----------- * SQRT(STEP/X0)
C-                            SQRT(3.)   P[MeV]*BETA
C-
C-                         When the cumulative track length since the last
C-                         kink (or since track beginning) given in DFL
C-                         is such that the above quantity is comparable
C-                         to the drift chamber accuracy, CDFACU, the kink
C-                         will be prepared.
C-                Inputs : Attention to DFBETA: it is set in DFINIT in the
C-                         pion mass hypothesis.
C-   Created
C-   Updated
C-
C----------------------------------------------------------------------
$$INCLUDE 'K$ITRK:CCONST.INC'
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:CDFWORK.INC'  ! 9/6/98 MXHIT=250
C
      INTEGER N,M,NPRHITS
      REAL PMEV,S,FACTOR,FACTM2
      COMMON /NBHITS/ NPRHITS 

      PMEV = 1000./ABS(DFKURV*DFSTHE)
      FACTOR = 13.6/PMEV/DFBETA
      FACTM2 = 1./FACTOR/FACTOR

      DFMLEN = (3.*CDFACU*CDFACU*FACTM2*TIDRL(1))**0.333333
      DFMLEN = AMAX1(DFMLEN,DFL(NDFL)/AMIN1(CDFNMS,DFNDGF))

      IF (DFMLEN .GT. .25*DFL(NDFL) .AND. NDFDIM.EQ.6) THEN
        RETURN
      ENDIF

      NDFDIM = 6

      CALL VZERO(MDF,MXHIT)

      N = NDF(NDF1)
      S = 0.
      DO WHILE (N.GT.0.AND.N.NE.NDFL)
        IF (DFL(N) - S .GE. DFMLEN) THEN
          IF (NDFDIM.GT.60) THEN
             CALL INERR(442)
             GOTO 30
          ENDIF
          NDFDIM = NDFDIM + 2
          MDF(N) = NDFDIM
          NDFMS(NDFDIM-6) = N
          NDFMS(NDFDIM-5) = N
          DFPMS(NDFDIM-6) = 0.
          DFPMS(NDFDIM-5) = 0.

C---      DFEMS = 1/(THETA M.S.)**2    -   CF NIM(56)

          DFEMS(NDFDIM-6) = FACTM2 * TIDRL(1)/(DFL(N)-S)
          DFEMS(NDFDIM-5) = FACTM2 * TIDRL(1)/(DFL(N)-S)
          S = DFL(N)
        ENDIF
        N = NDF(N)
      ENDDO
      MDF(NDFL) = 0

  30  NDFMS(NDFDIM-4) = 0
      DO N=1,MXHIT
        DO M=6,NDFDIM
          DFA(M,N) = 0.
        ENDDO
      ENDDO

      RETURN
      END
C
C*DK DFNEWW
C
C=======================================================================
C
      SUBROUTINE DFNEWW (NERRF1)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : To add new hits to an already found track, 
C-                         looking first in the direction of the particle,
C-                         and in a second iteration backward.          
C
C     Input parameters 
C     ================
      INTEGER NERRF1   ! error multiplier from DFFIT to DFADD to DFITER
C
C     Output parameters 
C     =================
C     None
C
C     Author:  	       	  
C     =======
C-
C-    Originally from ARGUS collaboration
C-    Modified June 1996 A. Calcaterra
C-
C----------------------------------------------------------------------
C
C       Global Declarations:-
C       =====================
C
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:CCONST.INC'
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:DHPT.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'  ! 9/6/98 MXHIT=250

C
C       External Functions:-
C       ====================

      INTEGER BLOCAT
      REAL    PROXIM

C       Local Declarations:-
C       ====================

      INTEGER   MAXJMP
      PARAMETER (MAXJMP=2)
      INTEGER STATUS,INDR,INDDATR,DHRENCO,INDP,INDDATP
      INTEGER NHITS
      INTEGER MNEXT,WTEST
      INTEGER ISIGN,N,LL
      INTEGER MP,MM,M,LD,L1,L2,L
      REAL    P,PHIW,PHIHIT,PHIDEL,PHITST,CROSS,DOT
      INTEGER MINC,SCAN,NDFCSV
      INTEGER MSTRT(2),MSTOP(2),MSTEP(2)
      INTEGER LFRST,LLAST
      INTEGER ITRN
      INTEGER NEWLR
      LOGICAL LOG1,LOG2

C  Locate bank DHRE, the running version of it

      STATUS = BLOCAT(IW,'DHRE',2,INDR,INDDATR)
      IF (STATUS.NE.YESUCC) THEN
        CALL ERLOGR('DFNEWW',ERWARN,0,STATUS,
     +      'Bank DHRE not found.')
        RETURN
      ENDIF 
      INDR    = INDDATR+IW(INDDATR+DHRHDS)
      NHITS   = IW(INDDATR+DHRNRO)
      DHRENCO = IW(INDDATR+DHRNCO)

C  Locate bank of DHPT pointers

      STATUS = BLOCAT(IW,'DHPT',1,INDP,INDDATP)
      IF (STATUS.NE.YESUCC) THEN
        CALL ERLOGR('DFNEWW',ERWARN,0,STATUS,
     +      'Bank DHPT not found.')
        RETURN
      ENDIF 
      INDP = INDDATP+IW(INDDATP+DHPHDS)

C =====  INITIALISE LOOP OVER HIT WIRES

      ISIGN = 1

C =====  AT ITERATION 1 THIS LOOP WORKS IN THE TRACK DIRECTION,
C =====  AND IT EXECUTES ONLY ONCE.
C =====  AT ITERATION 2 IT TRIES TO EXTEND THE TRACK AT THE INNER END
C        AND IT REPEATS UNTIL NO NEW POINTS HAVE BEEN ADDED.

 100  CONTINUE
      NDFCSV = NDFC
      N = NDF1
      DO WHILE (N.GT.0)
        LL = LDFL(N)
        IF (LL.GT.0) THEN

C =====  MP = SIGN OF D AZIMUTH / D S    (S = TRACK LENGTH)

          MP = ISIGN
          CROSS =  (DFPY(N)*DFX(N)-DFPX(N)*DFY(N))   /
     .            SQRT(DFX(N)*DFX(N)+DFY(N)*DFY(N))
          IF (CROSS .LT. 0.)  MP = - MP

          MM   = KDF(N)
          PHIW = TIDDP(LL)*(IDF(N)-1)

          MINC  = IW(INDP+DHPAPT+NHITS+MM-1)
          LFRST = IW(INDP+DHPPT1+LL-1)
          LLAST = IW(INDP+DHPPTL+LL-1)
          IF (MP.EQ.1) THEN
            MSTRT(1) = MINC+1
            MSTOP(1) = LLAST
            MSTEP(1) = 1
            MSTRT(2) = MINC-1
            MSTOP(2) = LFRST 
            MSTEP(2) = -1
          ELSE
            MSTRT(1) = MINC-1
            MSTOP(1) = LFRST
            MSTEP(1) = -1
            MSTRT(2) = MINC+1
            MSTOP(2) = LLAST 
            MSTEP(2) = 1
          ENDIF
          DO SCAN=1,2
            DO M = MSTRT(SCAN),MSTOP(SCAN),MSTEP(SCAN)
              MNEXT = IW(INDP+DHPAPT+M-1)
              ITRN  = IW(INDR+(MNEXT-1)*DHRENCO+DHRTRN)
              IF (ITRN.LE.0) THEN
                NEWLR  = IW(INDR+(MNEXT-1)*DHRENCO+DHRSLR)
                WTEST  = IW(INDR+(MNEXT-1)*DHRENCO+DHRWNR)
                PHITST = TIDDP(LL)*(WTEST-1)
                PHIDEL = PROXIM(PHITST-PHIW,0.)
                IF (ABS(PHIDEL) .LT. CDFPHI*TIDDP(LL)) THEN
                  IF (LL.NE.NEWLR) THEN
                    CALL ERLOGR('DFNEWW',ERWARN,0,STATUS,
     +              'Pointer crossing: a BAD error.')
                  ENDIF
                  CALL DFADD (MNEXT,NERRF1)
                ENDIF
              ENDIF
            ENDDO
          ENDDO

C =====   SEARCH IN THE NEXT LAYERS

        DOT = (DFPX(N)*DFX(N)+DFPY(N)*DFY(N))   /
     .       SQRT(DFX(N)*DFX(N)+DFY(N)*DFY(N))
        IF (DOT .GT. 0.)  THEN          ! TRACK IS PROPAGATING OUTWARD...
          IF (ISIGN.EQ.1) THEN          ! ...AND WE ARE LOOKING OUTWARD,
            L1 = MAX0(LL-1,1)           ! SO DECREASE LAYER INDEX!
            L2 = MAX0(LL-MAXJMP,1)      ! (ARGUS CONVENTION!)
            LD = -1  
          ELSE                          ! ...BUT WE ARE LOOKING INWARD!
            L1 = MIN0(LL+1,58)          ! SO INCREASE LAYER INDEX INSTEAD
            L2 = MIN0(LL+MAXJMP,58)     
            LD = +1  
          ENDIF
        ELSE                            ! TRACK IS PROPAGATING INWARD
          IF (ISIGN.EQ.1) THEN          ! (AND SO WE LOOK FIRST)
            L1 = MIN0(LL+1,58)          ! SO DECREASE LAYER INDEX!
            L2 = MIN0(LL+MAXJMP,58)     ! (ARGUS CONVENTION!)
            LD = +1  
          ELSE                          ! LATER, WILL LOOK OUTWARD
            L1 = MAX0(LL-1,1)           ! SO DECREASE LAYER INDEX. EASY. ;-)
            L2 = MAX0(LL-MAXJMP,1)
            LD = -1  
          ENDIF
        ENDIF
        PHIHIT = ATAN2(DFY(N),DFX(N)) - DFZ(N)*TIDST(LL)/TIDRA(LL)
        IF (PHIHIT.LT.0.)  P = P + PI2

C =====   NEXT LAYER = CHECK INNERMOST AND OUTERMOST LAYER

        DO L=L1,L2,LD
          IF (L.EQ.LL) GOTO 160
          LFRST = IW(INDP+DHPPT1+L-1)
          LLAST = IW(INDP+DHPPTL+L-1)
          IF (MP.EQ.1) THEN
            MSTRT(1) = LFRST
            MSTOP(1) = LLAST
            MSTEP(1) = 1
            MSTRT(2) = LLAST
            MSTOP(2) = LFRST
            MSTEP(2) = -1
          ELSE
            MSTRT(1) = LLAST
            MSTOP(1) = LFRST
            MSTEP(1) = -1
            MSTRT(2) = LFRST
            MSTOP(2) = LLAST
            MSTEP(2) = 1
          ENDIF
          DO M = MSTRT(1),MSTOP(1),MSTEP(1)
            MNEXT = IW(INDP+DHPAPT+M-1)
            ITRN  = IW(INDR+(MNEXT-1)*DHRENCO+DHRTRN)
            IF (ITRN.LE.0) THEN
              WTEST  = IW(INDR+(MNEXT-1)*DHRENCO+DHRWNR)
              PHITST = TIDDP(L)*(WTEST-1)
              PHIDEL = PROXIM(PHITST-PHIHIT,0.)
              IF (MP.EQ.1) THEN
                LOG1 = PHIDEL .GT. 0.
                LOG2 = PHIDEL .LT. CDFPHI*TIDDP(L)/(1.2*ABS(DOT))
              ELSE
                LOG1 = PHIDEL .LT. 0.
                LOG2 = PHIDEL .GT. -CDFPHI*TIDDP(L)/(1.2*ABS(DOT))
              ENDIF
              IF (LOG1 .AND. LOG2) THEN
                CALL DFADD (MNEXT,NERRF1)
              ENDIF
            ENDIF
          ENDDO
          DO M = MSTRT(2),MSTOP(2),MSTEP(2)      	       
            MNEXT = IW(INDP+DHPAPT+M-1)
            ITRN  = IW(INDR+(MNEXT-1)*DHRENCO+DHRTRN)
            IF (ITRN.LE.0) THEN
              WTEST  = IW(INDR+(MNEXT-1)*DHRENCO+DHRWNR)
              PHITST = TIDDP(L)*(WTEST-1)
              PHIDEL = PROXIM(PHITST-PHIHIT,0.)
              IF (MP.EQ.1) THEN
                LOG1 = PHIDEL .LT. 0.
                LOG2 = PHIDEL .GT. -CDFPHI*TIDDP(L)/(1.2*ABS(DOT))
              ELSE
                LOG1 = PHIDEL .GT. 0.
                LOG2 = PHIDEL .LT. CDFPHI*TIDDP(L)/(1.2*ABS(DOT))
              ENDIF
              IF (LOG1 .AND. LOG2) THEN
                CALL DFADD (MNEXT,NERRF1)
              ENDIF
            ENDIF
          ENDDO

 160    ENDDO

        ENDIF
 170    N = NDF(N)
      ENDDO

      IF (ISIGN.EQ.-1) THEN
        IF (NDFC .EQ. NDFCSV) RETURN
        GO TO 100
      ELSE
        ISIGN = - 1
        GO TO 100
      ENDIF

      END
C
C=======================================================================
      SUBROUTINE DFDEDX(ISIGN)
C=======================================================================
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Calculation of the energy loss, put in DFDPDX,
C-                         used in the subroutine DFPNT
C-   Created
C-   Updated     -G.Venanzoni  8/98 
C-                E. De Lucia 
C- 		  P. Pages	
C-
C- INPUT PARAMETER : ISIGN (+ or - 1)
C----------------------------------------------------------------------


$$INCLUDE 'K$ITRK:CCONST.INC'
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:CDFWORK.INC'  ! 9/6/98 MXHIT=250

      INTEGER ISIGN  
      REAL MOM,MASS,BETA
      REAL ACF,ZCF,DAL,ALI
      REAL DMOM,DENS       

      MOM=1./ABS(DFKURV*DFSTHE)
      MASS=PION_MASS
      BETA=MOM/SQRT(MASS**2+MOM**2)

      DENS=0.427E-3
      ACF=7.823
      ZCF=3.965
      DAL=0.000307*ZCF/ACF
      ALI=62500./ZCF**0.9
      DFDPDX=DAL/BETA**2
     +       *(LOG(ALI*(MOM/MASS)**2)-BETA**2)*DENS
      DFDPDX=DFDPDX/BETA
      DMOM=MOM-DFL(NDFL)*DFDPDX
      DFDPDX=SIGN(DFKURV**2*DFSTHE*DFDPDX,DFKURV)
	if(isign.eq.-1) DFDPDX =-DFDPDX
      RETURN
      END
C

C*DK DFNEXT
      SUBROUTINE DFNEXT (N1,N2,S)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Given the particle position and momentum
C-                         at a point "N1", a helyx segment of 3D-length S
C-                         is employed to compute position and momentum
C-                         at a point "N2". This routine implicitly takes 
C-                         input from vectors DFX/Y/Z and DFPX/Y/Z at N1
C-                         and modifies the same vectors at N2.
C-              IMPORTANT: "N1" and "N2" can also be the same.
C-
C-   Created
C-   Updated
C-
C----------------------------------------------------------------------
$$INCLUDE  'K$ITRK:CDFWORK.INC'  ! 9/6/98 MXHIT=250

      INTEGER N1,N2
      REAL S,SLAM,CLAM,C,PSI,SPSI,CPSI,A1
      REAL VN(3)
      REAL ANG1,ANG2,DFCTHE,PHIMS,THETMS
      REAL P1,P2,NSLAM,NCLAM
      COMMON /ANGLES/ ANG1(64),ANG2(64)

      DFCTHE=SQRT(1-DFSTHE**2)

C--------  GET VECTOR  VN = TANGENT CROSS H_FIELD ; CF KAPITZA(54)

      VN(1) = DFPY(N1) * DFHZ(N1) - DFPZ(N1) * DFHY(N1)
      VN(2) = DFPZ(N1) * DFHX(N1) - DFPX(N1) * DFHZ(N1)
      VN(3) = DFPX(N1) * DFHY(N1) - DFPY(N1) * DFHX(N1)

C--------  LAM = LOCAL DIP ANGLE  ; CF NIM(37)

      SLAM = DFHX(N1)*DFPX(N1) + DFHY(N1)*DFPY(N1) + DFHZ(N1)*DFPZ(N1)
      IF (ABS(SLAM).GT.0.999) THEN
        CLAM = 0.
      ELSE
        CLAM = SQRT (1. - SLAM**2)
      ENDIF

C--------  PSI = TURNING ANGLE OF ORBIT ; CF NIM(32,34)

      C = DFH(N1) * (DFKURV + DFL(N2) * DFDPDX) * DFSTHE
      PSI = C * S
      SPSI = SIN (PSI)
      CPSI = 1. - COS (PSI)

C--------  NEW XYZ  ; CF KAPITZA(55)

      A1 = (PSI - SPSI) * SLAM
      DFX(N2) = DFX(N1) +
     +         (SPSI*DFPX(N1) + CPSI*VN(1) + A1*DFHX(N1)) / C
      DFY(N2) = DFY(N1) +
     +         (SPSI*DFPY(N1) + CPSI*VN(2) + A1*DFHY(N1)) / C
      DFZ(N2) = DFZ(N1) +
     +         (SPSI*DFPZ(N1) + CPSI*VN(3) + A1*DFHZ(N1)) / C

C--------  NEW DIRECTION  ; CF KAPITZA(56)

      A1 = CPSI * SLAM
      CPSI = 1. - CPSI
      DFPX(N2) = CPSI * DFPX(N1) + SPSI * VN(1) + A1 * DFHX(N1)
      DFPY(N2) = CPSI * DFPY(N1) + SPSI * VN(2) + A1 * DFHY(N1)
      DFPZ(N2) = CPSI * DFPZ(N1) + SPSI * VN(3) + A1 * DFHZ(N1)

C--------  MULTIPLE SCATTERING

      IF (MDF(N2).NE.0 .AND. N1.NE.N2) THEN

         NCLAM=CLAM*COS(ANG2(MDF(N2)-6))
     +         +DFPZ(N2)*SIN(ANG2(MDF(N2)-6))
         IF (ABS(NCLAM).LT.0.99999)THEN
             NSLAM=SQRT(1.-NCLAM**2)
         ELSE
             NSLAM=0.
         ENDIF
         CPSI=COS(PSI)
         A1 = (1-CPSI) * NSLAM
         DFPX(N2) = CPSI * DFPX(N1) + SPSI * VN(1) 
     +              + A1 * DFHX(N1)
         DFPY(N2) = CPSI * DFPY(N1) + SPSI * VN(2) 
     +              + A1 * DFHY(N1)
         DFPZ(N2) = DFPZ(N2)*COS(ANG2(MDF(N2)-6))
     +              - CLAM*SIN(ANG2(MDF(N2)-6)) 

         A1 = DFPX(N2)
         DFPX(N2) = A1 *       COS (ANG1(MDF(N2)-6)) -
     +           DFPY(N2) * SIN (ANG1(MDF(N2)-6))
         DFPY(N2) = A1 *       SIN (ANG1(MDF(N2)-6)) +
     +           DFPY(N2) * COS (ANG1(MDF(N2)-6))

         A1 = DFPX(N2)**2 + DFPY(N2)**2 + DFPZ(N2)**2
         A1 = 2. / (1. + A1)
         DFPX(N2) = DFPX(N2) * A1
         DFPY(N2) = DFPY(N2) * A1
         DFPZ(N2) = DFPZ(N2) * A1

      ENDIF

      RETURN
      END
C
C*DK DFPNT
      SUBROUTINE DFPNT (N1,N2,S)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Given the particle position and unit vector
C-                         at the measured point "N1", the track is LINEARLY 
C-                         extrapolated to the point of CA to wire N2. 
C-                         Also, the magnetic field must be
C-                         recalculated, for now it is assumed uniform.
C-
C     Input parameters 
C     ================
      INTEGER N1,N2    ! index of the 2 hits in the 1-track common /CDFWORK/
C
C     Output parameters 
C     =================
      REAL S           ! distance from point N1 to point of CA to N2.
C
C-   Created
C-   Updated
C-
C----------------------------------------------------------------------
$$INCLUDE 'K$ITRK:CCONST.INC'
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'  ! 9/6/98 MXHIT=250

      REAL WT,X(3),H(3)
      REAL EPSILON /1.E-6/

      DFH(N1) = TIFLAV

      X(1) = DFX(N1)
      X(2) = DFY(N1)
      X(3) = DFZ(N1)
      CALL MGFLD(X,H)

      CALL VSCALE(H,CONVERS,H,3)
      DFHX(N1) = H(1) / DFH(N1)
      DFHY(N1) = H(2) / DFH(N1)
      DFHZ(N1) = H(3) / DFH(N1)

      IF (LDFL(N2).GT.0)  THEN

C     THIS IS A POINT WHERE A REAL DISTANCE MEASUREMENT EXISTS

        WT = DFVX(N2)*DFPX(N1) + DFVY(N2)*DFPY(N1)
     +                                     + TIDSC(LDFL(N2))*DFPZ(N1)
        IF (ABS(1.-WT*WT) .LT. EPSILON) THEN
          IF     (WT .LE. -1.) THEN
             WT = -1. - EPSILON
          ELSEIF (WT .LE.  0.) THEN
             WT = -1. + EPSILON
          ELSEIF (WT .LE.  1.) THEN
             WT =  1. - EPSILON
          ELSE
             WT =  1. + EPSILON
          ENDIF
        ENDIF
        S = ((DFWX(N2) - DFX(N1)) * (DFPX(N1) - WT * DFVX(N2)) +
     +       (DFWY(N2) - DFY(N1)) * (DFPY(N1) - WT * DFVY(N2)) -
     +                  DFZ(N1)  * (DFPZ(N1) - WT * TIDSC(LDFL(N2)))) /
     +      (1. - WT * WT)
      ELSE
      
C     THIS IS EITHER A POINT PREVIOUSLY REJECTED IN THE FIT ITERATIONS,
C     OR A FICTITIOUS POINT, INTRODUCED TO TREAT MULTIPLE SCATTERING.

        S = 0.
      ENDIF

      RETURN
      END
C
C*DK DFLIP
C
C=======================================================================
C
      SUBROUTINE DFLIP (NERRF1)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : In case where the drift distance is small
C                          (typically 3-4 mm) it is possible that 
C                          the sign of the drift distance came out wrong
C                          from Pattern Recognition.
C                          This routine tries to flip all (small) drift 
C                          distances, starting from the wire with the 
C                          worst residual.
C
C     Author: A. Calcaterra
C     =======
C-
C-    Created  10-14-96
C-
C----------------------------------------------------------------------
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:CDFWORK.INC'  ! 9/6/98 MXHIT=250


      INTEGER NERRF1
      INTEGER STATUS,BLOCAT
      INTEGER INDR,INDDATR,DHRENCO
      INTEGER INDICES(MXHIT),FLIPPED(MXHIT)

      LOGICAL IN_RANGE, BETTER, NOTFLP
      LOGICAL SAV_HITS,ITERATE
      INTEGER N,NSORT,NFLIP
      REAL    OTHER,PREV_R,CHISAV
      REAL    DMIN,DMAX
      DATA    DMIN/0.000/,DMAX/3./
      REAL    RSORT(MXHIT),DFOTH(MXHIT)

      STATUS = BLOCAT(IW,'DHRE',2,INDR,INDDATR)
      IF (STATUS.NE.YESUCC) RETURN
      DHRENCO = IW(INDDATR+DHRNCO)
      INDR = INDDATR+IW(INDDATR+DHRHDS)
      CALL VZERO(FLIPPED,MXHIT)

C  Select all wires with small drift distance in order of decreasing
C  (absolute) normalized residual. Flip wires only once please !!

      ITERATE = .TRUE.

*************************************************************
      DO WHILE (ITERATE)
*************************************************************

         NSORT = 0
         N = NDF1
         DO WHILE (N.GT.0)
            OTHER  = DFCH(N) - 2.*DFD(N)
            IN_RANGE = ABS(DFD(N)) .LT. DMAX .AND.
     +                 ABS(DFD(N)) .GT. DMIN
            BETTER = ABS(OTHER) .LT. ABS(DFCH(N))
            NOTFLP = FLIPPED(N).EQ.0
            IF (IN_RANGE .AND. BETTER .AND. NOTFLP) THEN
               NSORT = NSORT+1
               INDICES(NSORT) = N
               RSORT(N) = ABS(DFCH(N))-ABS(OTHER)
               DFOTH(N) = OTHER
            ENDIF
            N = NDF(N)
         ENDDO

C  Are there (more) candidates for sign flipping?

         IF (NSORT.EQ.0) THEN
            ITERATE = .FALSE.
            GOTO 999
         ENDIF

C  Yes, do the sorting, flip the worst hit, and try to refit the track

         CALL SORTZV(RSORT,INDICES,NSORT,1,-1,-1)
         NFLIP = INDICES(1)
         FLIPPED(NFLIP) = 1
         
C Let's save all info about track before calling DFITER....

         SAV_HITS = .FALSE.
         NDFERR = 0
         CALL DFSAVE(NFLIP,SAV_HITS)
         CHISAV = DFCHIN
         PREV_R = RW(INDR+(KDF(NFLIP)-1)*DHRENCO+DHRRAD)
         RW(INDR+(KDF(NFLIP)-1)*DHRENCO+DHRRAD) = -PREV_R
         DFD(NFLIP) = -DFD(NFLIP)
 100     CALL DFITER (NERRF1*CDFDC1,CDFM1L)
 
C  Did something BAD happen ?

         IF (NDFERR.NE.0) THEN
            NERRF1=NERRF1+1
            CALL INERR(408)

C  Some error conditions: (Chi2 increasing) and (too many iterations)
C  invite to try again the fit relaxing the first cut. The same could 
C  apply in principle for (pred chi2 wors), NDFERR=3

            IF (NDFERR.NE.2 .AND. NDFERR.NE.6) GO TO 200
            IF (DFCHIN.LT.CHISAV) THEN
               IF (NERRF1.LT.15) THEN
                  GOTO 100
               ENDIF
            ENDIF
 200        CONTINUE
            RW(INDR+(KDF(NFLIP)-1)*DHRENCO+DHRRAD) = PREV_R
            
C     It's better to restore previous situation !

            CALL DFRESTORE(NFLIP,SAV_HITS)
            CALL HFILL(408,0.,0.,1.)
         ELSE
            CALL HFILL(409,(DFCHIN-CHISAV)/DFNDGF,0.,1.)
            IF (DFCHIN.GT.CHISAV) THEN
               RW(INDR+(KDF(NFLIP)-1)*DHRENCO+DHRRAD) = PREV_R
               
C     It's better to restore previous situation!

               CALL DFRESTORE(NFLIP,SAV_HITS)
               CALL HFILL(408,1.,0.,1.)
            ELSE
               CALL HFILL(408,2.,0.,1.)
            ENDIF
         ENDIF

 999     CONTINUE
  
*************************************************************
      ENDDO
*************************************************************

      RETURN
      END
C
C*DK DFREJ
C
C=======================================================================
C
      SUBROUTINE DFREJ (NERRF1,CHIMAX,CHIFAC)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : This deceptively short and simple routine does
C-                         one of the most complicate jobs I have ever seen:
C-   it keeps trying to obtain better track fits by picking the point giving 
C-   the biggest contribution to the chi^2 and doing the following:            
C-   1) test if the zeroth-order approximation to the new fit will give 
C-      a smaller overall chi^2.
C-   2) If yes, re-fit the track with DFITER
C-   3) If the worst point is now another one, do the same to the other point.
C-   4) Repeat until EITHER this worst-contribution is smaller than "CHIMAX" 
C-      OR it is smaller than "CHIFAC"*the average chi^2 / point.
C-   5) At that point, it is judged that the fit has already improved as much 
C-      as possible: ALL drift signs are switched to the most favorable case, 
C-      and a final fit will be remade in DFFIT.
C-   6) If, during the iteration, one of the reversals is anticipated as 
C-      UNSUCCESSFUL (NO at point 2) above), and the worst contribution STILL 
C-      is bigger than "CHIMAX", the point is killed and the fit is repeated 
C-      without that point.
C-   7) If, during the iteration, even after a successful fit the worst point
C-      does not change, the test at point 4) is made. If it fails (meaning
C-      still more improvement is requested) the point is killed and a new
C-      "worst point" is calculated (via DFITER) and examined.
C-   8) In the original routine there was the possibility of an infinite loop
C-      when the worst possible chi square contribution oscillates between
C-      two numbers. This actually happened! So the ATTEMPTS are limited to
C-      the actual number of points.
C-
C-   Created
C-   Updated
C-
C----------------------------------------------------------------------
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'C$INC:JOBSTA.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'  ! 9/6/98 MXHIT=250

      INTEGER NERRF1
      REAL    CHIMAX,CHIFAC

      INTEGER STATUS,BLOCAT
      INTEGER INDR,INDDATR,DHRENCO
      INTEGER N,NPRHITS
      REAL CHIPART
      REAL    ATTEMPTS
      REAL    OTHER,PREV_R,CHISAV
      LOGICAL SAV_HITS
      COMMON /NBHITS/ NPRHITS 
      
      CALL VZERO(CHIPART,MXHIT)

      STATUS = BLOCAT(IW,'DHRE',2,INDR,INDDATR)
      IF (STATUS.NE.YESUCC) RETURN
      DHRENCO = IW(INDDATR+DHRNCO)
      INDR = INDDATR+IW(INDDATR+DHRHDS)

      ATTEMPTS = 0.
 10   IF (DFMCH.LT.CHIMAX .OR.
     +    DFMCH.LT.DFCHIN*CHIFAC/(DFNDGF+5.) .OR.
     +    ATTEMPTS.GT.DFNDGF+5.) GOTO 200

C-------  TRY THE OTHER SIGN OF THE DRIFT DISTANCE

      N = NDFMCH
      CHISAV = DFCHIN
      OTHER = DFCH(N) - 2.*DFD(N)
      IF (ABS(DFCH(N)) .GE. ABS(OTHER)) THEN
        ATTEMPTS = ATTEMPTS+1.
        PREV_R = RW(INDR+(KDF(N)-1)*DHRENCO+DHRRAD)
        RW(INDR+(KDF(N)-1)*DHRENCO+DHRRAD) = -PREV_R
        
C  Let's save all info about track before calling DFITER....

        SAV_HITS = .FALSE.
        NDFERR = 0
        CALL DFSAVE(N,SAV_HITS)
        DFD(N)     = -DFD(N)
        DFCH(N)    = OTHER
 100    CALL DFITER (NERRF1*CDFDC1,CDFM1L)
        IF (NDFERR.NE.0) THEN
         NERRF1=NERRF1+1
         CALL INERR(408)

C  Some error conditions: (Chi2 increasing) and (too many iterations)
C  invite to try again the fit relaxing the first cut. The same could 
C  apply in principle for (pred chi2 wors), NDFERR=3

          IF (NDFERR.NE.2 .AND. NDFERR.NE.6) GO TO 400
          IF(DFCHIN.LT.CHISAV)THEN
           IF (NERRF1.LT.15) THEN
            GOTO 100
           ENDIF
          ENDIF
 400      CONTINUE
          RW(INDR+(KDF(N)-1)*DHRENCO+DHRRAD) = PREV_R
          
C   It's better to restore previous situation !

          CALL DFRESTORE(N,SAV_HITS)
        ELSE
          IF (DFCHIN.GT.CHISAV) THEN
             RW(INDR+(KDF(N)-1)*DHRENCO+DHRRAD) = PREV_R
             
C   It's better to restore previous situation  !

             CALL DFRESTORE(N,SAV_HITS)
          ENDIF
        ENDIF
        IF (N.NE.NDFMCH) GOTO 10
      ENDIF

C-------  REJECT WIRE

      IF (DFMCH.LT.CHIMAX .OR.
     +    DFMCH.LT.DFCHIN*CHIFAC/(DFNDGF+5.)) GOTO 200
      IF (DFMCH.LT.CHIMAX) GOTO 200
      CHISAV = DFCHIN
      CALL DFKILL(N)
      
      IF (NDFERR.NE.0) THEN
        RETURN
      ENDIF
300   CALL DFITER (NERRF1*CDFDC1,CDFM1L)
      IF (NDFERR.NE.0) THEN
         NERRF1=NERRF1+1
         CALL INERR(408)

C  Some error conditions: (Chi2 increasing) and (too many iterations)
C  invite to try again the fit relaxing the first cut. The same could 
C  apply in principle for (pred chi2 wors), NDFERR=3

         IF (NDFERR.NE.2 .AND. NDFERR.NE.6) RETURN
         IF (DFCHIN.LT.CHISAV)THEN
            IF (NERRF1.LT.15) GOTO 300
         ENDIF
      ENDIF

      GOTO 10

C-------  TRY ALL OTHER SIGNS OF THE DRIFT DISTANCE

 200  CONTINUE

      RETURN
      END
C
C*DK DFSTOR
C
C=======================================================================
C
      SUBROUTINE DFSTOR(NPASS)
C 
$$IMPLICIT

C     FILL FIT RESULTS INTO BANK "DTFS"
C     author : A. Antonelli + S. Calcaterra - march 1995

$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$ITRK:CFLAGS.INC'
$$INCLUDE 'K$ITRK:CCONST.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'    !<
C
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$ITRK:DTFS.INC'
$$INCLUDE 'K$ITRK:DHSP.INC'
$$INCLUDE 'C$INC:JOBSTA.INC'

C       External Functions:-
C       ====================

      INTEGER BTYMKG
      REAL    PROB

C       Local Declarations:-
C       ====================

      INTEGER KINENUM,PIDNUM  

      INTEGER STATUS,IND,INDDAT,INDP,INDDATP,DHSPNCO
      INTEGER BNKSIZ,II,N
      INTEGER NHIPT,NHITF
      INTEGER NPASS
      REAL    CH2N
      LOGICAL REVERSE
      REAL*4  XST(3),RTOBEAM,ZTOBEAM,S
      CHARACTER*32 DTFSBNK
      DATA DTFSBNK/'13I4,30R4,I4,R4,2I4,6R4,XXXI4'/
      CHARACTER*15 DHSPBNK
      DATA DHSPBNK/'4I4,XXX(I4,7R4)'/

C       Executable Code:
C       =================
       
      NHIPT = IW(JDPRS+DPRPOS)+IW(JDPRS+DPRNEG)
      NHITF = NFITNEG + NFITPOS
      IF (NHITF.GT.999) THEN
         CALL INERR(401)
         RETURN
      ENDIF

C       Create the fitted track bank 
C       =============================

      WRITE(DTFSBNK(25:27),'(I3)') NHITF
      STATUS = BTYMKG(IW,'DTFS',ITR,DTFSBNK,BNKSIZ,IND,INDDAT)
      IF (STATUS.NE.YESUCC) THEN
        CALL INERR(490)
        RETURN
      ENDIF

C       Create the space points bank 
C       =============================

      WRITE(DHSPBNK(5:7),'(I3)') NHITF
      STATUS = BTYMKG(IW,'DHSP',ITR,DHSPBNK,BNKSIZ,INDP,INDDATP)
      IF (STATUS.NE.YESUCC) THEN
        CALL INERR(491)
        RETURN
      ENDIF

C       Fill bank DTFS first
C       ====================

      IW(INDDAT+DTFHDS) = 2
      IW(INDDAT+DTFVRN) = NPASS
      INDDAT = INDDAT + IW(INDDAT+DTFHDS)
      IW(INDDAT+DTFINH) = 10000*IW(JDPRS+DPRPOS)+IW(JDPRS+DPRNEG)
      IW(INDDAT+DTFNHF) = 10000*NFITPOS+NFITNEG
      RW(INDDAT+DTFLNG) = DFL(NDFL)
      RW(INDDAT+DTFXCO) = DFX(NDF1)
      RW(INDDAT+DTFYCO) = DFY(NDF1)
      RW(INDDAT+DTFZCO) = DFZ(NDF1)
      RW(INDDAT+DTFCUR) = DFKURV
      RW(INDDAT+DTFCTT) = DFCTGT
      RW(INDDAT+DTFPHI) = DFPHI
      RW(INDDAT+DTFCVM)   = XI(1,1)
      RW(INDDAT+DTFCVM+1) = XI(2,1)
      RW(INDDAT+DTFCVM+2) = XI(3,1)
      RW(INDDAT+DTFCVM+3) = XI(4,1)
      RW(INDDAT+DTFCVM+4) = XI(6,1)
      RW(INDDAT+DTFCVM+5) = XI(2,2)
      RW(INDDAT+DTFCVM+6) = XI(3,2)
      RW(INDDAT+DTFCVM+7) = XI(4,2)
      RW(INDDAT+DTFCVM+8) = XI(6,2)
      RW(INDDAT+DTFCVM+9) = XI(3,3)
      RW(INDDAT+DTFCVM+10)= XI(4,3)
      RW(INDDAT+DTFCVM+11)= XI(6,3)
      RW(INDDAT+DTFCVM+12)= XI(4,4)
      RW(INDDAT+DTFCVM+13)= XI(6,4)
      RW(INDDAT+DTFCVM+14)= XI(6,6)
      RW(INDDAT+DTFCHI) = DFCHIN
      RW(INDDAT+DTFPCH) = PROB(DFCHIN,NHITF-5)
      RW(INDDAT+DTFXLP) = DFX(NDFL)
      RW(INDDAT+DTFYLP) = DFY(NDFL)
      RW(INDDAT+DTFZLP) = DFZ(NDFL)
      RW(INDDAT+DTFCLP) = ABS (DFKURV + DFL(NDFL) * DFDPDX)

      IF (SQRT(DFPX(NDFL)**2 + DFPY(NDFL)**2).GT.1.E-20) THEN
        RW(INDDAT+DTFTLP)= DFPZ(NDFL)/SQRT(DFPX(NDFL)**2+DFPY(NDFL)**2)
        RW(INDDAT+DTFPLP)= ATAN2 (DFPY(NDFL),DFPX(NDFL))
      ENDIF
      IF(RW(INDDAT+DTFPLP).LT.0.)RW(INDDAT+DTFPLP)=RW(INDDAT+DTFPLP)+PI2

C------  MULTIPLE SCATTERING

      IW(INDDAT+DTFMSK)= NDFDIM - 6
      RW(INDDAT+DTFCHM)= 0.
      IF (NDFDIM.GT.6)  RW(INDDAT+DTFCHM)= DFCMS2
      IW(INDDAT+DTFPVS)= 0
      N = NDF1
      II = 0
      DO WHILE (N.GT.0)
       IF (LDFL(N) .GT. 0) THEN
         IW(INDDAT+DTFFHA+II)= KDF(N)
         II = II+1
       ENDIF
       N = NDF(N)
      ENDDO

C=======  PROJECT THIS TRACK (IF IT HAS POINTS IN AN INNER LAYER) 
C=======  TOWARD THE BEAM AXIS. FLAG THE TRACK AS COMING FROM THE IP

      ZTOBEAM = -1000.
      RTOBEAM =  1000.
      IF (LDFL(NDF1).EQ.57 .OR. LDFL(NDF1).EQ.58) THEN
        REVERSE = .TRUE.
        XST(1) = DFX(NDF1)
        XST(2) = DFY(NDF1)
        XST(3) = DFZ(NDF1)
        CALL DFTOIP(XST,DFKURV,DFCTGT,DFPHI,REVERSE,ZTOBEAM,RTOBEAM,S)
        IF (RTOBEAM.LE.3. .AND. ABS(ZTOBEAM).LE.10.) THEN
          IW(INDDAT+DTFCEN) = 1
        ENDIF
      ENDIF

C       And now bank DHSP 
C       =================

      IW(INDDATP+DHSHDS) = 4
      IW(INDDATP+DHSVRN) = 1
      IW(INDDATP+DHSNRO) = NHITF
      IW(INDDATP+DHSNCO) = 8
      DHSPNCO = IW(INDDATP+DHSNCO)
      INDP = INDDATP + IW(INDDATP+DHSHDS)
      N = NDF1
      DO WHILE (N.GT.0)
       IF (LDFL(N) .GT. 0) THEN
         IW(INDP+DHSADR) = IW(JDPRS1+DPRLWI*(N-1)+DPRIWI)
         RW(INDP+DHSXCO) = DFX(N)
         RW(INDP+DHSYCO) = DFY(N)
         RW(INDP+DHSZCO) = DFZ(N)
         CH2N = - DFCH(N)
         DO II=1,NDFDIM
           CH2N = CH2N + XX(II,NDFDIM+2)*DFA(II,N)
         ENDDO
         RW(INDP+DHSCHN) = CH2N
         RW(INDP+DHSBET) = DFB(N)
         RW(INDP+DHSPHT) = DFF(N)
         RW(INDP+DHSDRD) = DFD(N)-DFCH(N)
         INDP = INDP + DHSPNCO
       ENDIF
       N = NDF(N)
      ENDDO

      RETURN
      END
C
C*DK DFTOIP
C
C=======================================================================
C
      SUBROUTINE DFTOIP(XSTART,CURV,CTGT,PHI0,REVERSE,ZMIN,RMIN,S)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Given the particle position and unit vector
C-                         DFTOIP finds the point of closest approach of
C-                         the track to the beam axis.
C-
C     Author: A. Calcaterra
C     =======
C-
C-    Created Mar 1st 1996
C-
C----------------------------------------------------------------------
      REAL*4 XSTART(3),CURV,CTGT,PHI0,S
      LOGICAL REVERSE
      REAL*4 ZMIN,RMIN
$$INCLUDE 'K$ITRK:CCONST.INC'

      REAL RHO,Q,XCEN,YCEN,STEP,DSTEP
      REAL OLD_Z,OLD_R,XSTOP(3),NEW_R
      LOGICAL HOMING

      RHO  = 1./ABS(CURV*TIFLAV)
     Q    = SIGN(1.,CURV)
      XCEN = XSTART(1)+Q*RHO*SIN(PHI0)
      YCEN = XSTART(2)-Q*RHO*COS(PHI0)

      HOMING = .TRUE.
      OLD_R = SQRT(XSTART(1)**2+XSTART(2)**2)
      STEP = OLD_R/2.
      IF (REVERSE) STEP = -STEP
      DO WHILE (HOMING .AND. ABS(STEP).GT.0.1)
        XSTOP(1) = XCEN-RHO*Q*SIN(PHI0-Q*STEP/RHO)
        XSTOP(2) = YCEN+RHO*Q*COS(PHI0-Q*STEP/RHO)
        XSTOP(3) = XSTART(3)+STEP*CTGT
        NEW_R    = SQRT(XSTOP(1)**2+XSTOP(2)**2)
        DSTEP    = NEW_R/2.
        IF (REVERSE) DSTEP = -DSTEP
        STEP     = STEP+DSTEP
        HOMING   = NEW_R.LT.OLD_R
        OLD_R    = NEW_R
        OLD_Z    = XSTOP(3)
      ENDDO

     S    = STEP
      RMIN = OLD_R
      ZMIN = OLD_Z

      RETURN
      END
C
C*DK DFTRAC
C
C=======================================================================
C
      SUBROUTINE DFTRAC(FAST_SWIM)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Given the particle position and unit vector
C-                         at the measured point "NDF1", a succession
C-                         of helical segments is found, joining points
C-                         of closest approach to successive hit wires.
C-             IMPORTANT : the length output from DFPNT has the intrinsic
C-                         meaning of a CORRECTION, and it should be "small".
C-                         The length input to DFNEXT is a CORRECTION, and
C-                         must come from DFPNT, when the first 2 arguments
C-                         are the same, is a STEP when they are different.
C-
C-   Created
C-   Updated
C-
C----------------------------------------------------------------------
      LOGICAL FAST_SWIM
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:CDFWORK.INC'  

      INTEGER N1,N2,M
      REAL STEP, CORRECTION
      REAL ANG1,ANG2
      COMMON /ANGLES/ ANG1(64),ANG2(64)

      IF (NDFDIM.GT.6) THEN
         DO M=7,NDFDIM,2
            ANG1(M-5) = DFPMS(M-5)
            ANG2(M-5) = DFPMS(M-4)
         ENDDO         
      ENDIF   

      NDFERR = 0
      N1 = NDF1
      N2 = NDF(N1)
      IF (FDFAST .AND. FAST_SWIM) THEN

C--------  FAST TRACING

        DO WHILE (N2.NE.0)
           DFL(N2) = DFL(N1) + DFS(N1)
           CALL DFNEXT(N1,N2,DFS(N1))
           N1 = NDF(N1)
           N2 = NDF(N2)
        ENDDO
      ELSE

C--------  SLOW TRACING : START CORRECTING THE POSITION OF THE 1ST POINT

        CALL DFPNT (N1,N1,CORRECTION)

        IF (ABS(CORRECTION) .GT. AMIN1 (0.2*DFSTLC,0.2))  THEN
           DFL(N1) = DFL(N1) + CORRECTION
           CALL DFNEXT (N1,N1,CORRECTION)
           CALL DFPNT (N1,N1,CORRECTION)
           DFCTGT = DFPZ(N1) / SQRT (DFPX(N1)**2 + DFPY(N1)**2)
           DFSTHE = 1. / SQRT (1. + DFCTGT**2)
           DFPHI  = ATAN2 (DFPY(N1) , DFPX(N1))
        ENDIF

        DFL(N1) = 0.
        STEP = DFS(N1)
        DO WHILE (N2.NE.0)
          DFL(N2) = DFL(N1) + STEP
          CALL DFNEXT (N1,N2,STEP)
          CALL DFPNT (N2,N2,CORRECTION)
          IF (CORRECTION .LT. -CDFSTL) THEN
            CALL ERLOGR('DFTRAC',ERWARN,0,0,
     +          'Large negative step length: wrong order in D3SORT.')
            NDFERR = 7
            RETURN
          ENDIF
          DFS(N1) = DFS(N1) + CORRECTION
          IF (ABS(CORRECTION) .LE. DFSTLC)  THEN
            STEP = DFS(N2) + CORRECTION
          ELSE
            DFL(N2) = DFL(N2) + CORRECTION
            CALL DFNEXT (N2,N2,CORRECTION)
            CALL DFPNT (N2,N2,CORRECTION)
            STEP = DFS(N2)
          ENDIF
          N1 = NDF(N1)
          N2 = NDF(N2)
        ENDDO
      ENDIF

      RETURN
      END
C
C*DK INERR
C
C=======================================================================
C
      SUBROUTINE INERR(IENUMB)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Definition of error codes
C-
C-   Created   1-JUL-1992   Alexander Andryakov
C-   Updated  11-OCT-1994   Alexander Andryakov
C-
C----------------------------------------------------------------------
      INTEGER IENUMB,IHIST
      REAL    CODE

      IHIST = 100*(IENUMB/100)
      CODE = FLOAT(MOD(IENUMB,100))
      CALL HFILL(IHIST,CODE,0.,1.)

      RETURN
      END
C
C*DK MGFLD
C
C=======================================================================
C
      SUBROUTINE MGFLD(X,H)
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : Calculate magnetic field inside drift chamber
C-                         Magnetic field is supposed to be constant
C-                         H(0,0,Hz)
C-
C-   Created   1-JUL-1992   Alexander Andryakov
C-   Updated   7-jun-1995   A.Andryakov
C-                          Magnetic field in the track fit is in units of
C-                          kGauss*0.00029979 (this was the major change
C-                          of the present code update)
C-                    B U T the vertex fit uses magnetic field in units of
C-                          kGauss only. Current version of the package (p.r.
C-                          +t.f.+v.f.) is self-consistent in this sence.
C-                   !!!!!  Be very careful when creating the real m.f. map
C-                   !!!!!  routine and keep in mind the above difference.
C-
C----------------------------------------------------------------------
$$INCLUDE 'K$ITRK:CCONST.INC'
      REAL X(3), H(3)
      REAL BRADL/0.000/

      H(1) = 0.
      H(2) = TIFLAV*BRADL/CONVERS
      H(3) = TIFLAV*(1.-0.5*BRADL*BRADL)/CONVERS

      RETURN
      END
C
C*DK DFSAVE
C
C=======================================================================
C
      Subroutine DFSAVE(NH,HITS)
C==============================================================
C-
C-  Purpose and methods:
C-
C-  Stores vital information about partially fitted tracks.
C-  It should be called before calling  DFITER, so in case
C-  something BAD happens a subsequent call to routine DFRESTORE
C-  may be done to restore the previous situation.
C-  By default it saves the TRACK PARAMETERS,the drift dist. 
C-  of hit NH and its error (useful when hit NH is going to 
C-  be flipped), the STEP LENGTH AT FIRST HIT, the error flag NDFERR
C-  the guessed chisq DFCHIN, the pointer to the hit contributing
C-  most to chisq NDFMCH, the maximum individual chisq
C-  DFMCH and multiple scattering parameters DFPMS.
C-
C-  Input parameters:
C-
C-  Integer    NH      The current hit, whose Drift Distance is to be
C-                     saved together with its error
C-
C-
C-  Logical    HITS    If .TRUE. saves also the hits chain NDF and
C-                     all related info: DFD,DFE,DFS,DFL vectors,
C-                     NFITPOS and NFITNEG and all multiple scattering
C-                     related infos: NDFDIM,MDF,NDFMS,DFEMS
C-
C-  N.B. 
C-        DFSAVE DOES NOT DEAL WITH DRIFT DISTANCE IN DHRE2 !!!
C-
C-  Created: Feb 1998 F. Ambrosino
C-
C===============================================================
$$IMPLICIT
$$INCLUDE 'K$ITRK:CDFWORK.INC'  
$$INCLUDE 'K$ITRK:DFSAV.INC'

      INTEGER N,M,NH
      LOGICAL HITS

      IF(HITS) THEN
         NDF1SAVE = NDF1
         NDFLSAVE = NDFL
         NDFDIMSAVE = NDFDIM
         N = NDF1
         M = 0
         DO WHILE(N.GT.0)
            M = M + 1
            NDFSAVE(N) = NDF(N)
            DFDSAVE(N) = DFD(N)
            DFERRSAVE(N) = DFE(N)
            DFSSAVE(N)   = DFS(N)
            DFLSAVE(N)   = DFL(N)
            MDFSAVE(N)   = MDF(N)
            N = NDF(N)
         ENDDO

         NHITSAVE = M

         DO M = 2,(NDFDIM-5)
            NDFMSSAVE(M) = NDFMS(M)
            DFEMSSAVE(M) = DFEMS(M)
         ENDDO

         NPOSSAVE   = NFITPOS
         NNEGSAVE   = NFITNEG
         
         SAVED_HITS = .TRUE.
      ENDIF
      
         NDFERRSAVE = NDFERR
         NMCHSAVE   = NDFMCH
         DFMCHSAVE  = DFMCH
         DFSAV( 1) = DFKURV
         DFSAV( 2) = DFCTGT
         DFSAV( 3) = DFSTHE
         DFSAV( 4) = DFPHI
         DFSAV( 5) = DFX(NDF1)
         DFSAV( 6) = DFY(NDF1)
         DFSAV( 7) = DFZ(NDF1)
         DFSAV( 8) = DFPX(NDF1)
         DFSAV( 9) = DFPY(NDF1)
         DFSAV(10) = DFPZ(NDF1)
         DFSAV(11) = DFCHIN
         DFSAV(12) = DFD(NH)
         DFSAV(13) = DFE(NH)
         DFSAV(14) = DFS(NDF1)
         
C------- Multiple scattering

         DO M = 2,(NDFDIM-5)
            DFPMSSAVE(M) = DFPMS(M)
         ENDDO

         SAVED_PARA = .TRUE.

      Return
      End
C
C*DK DFRESTORE
C
C=======================================================================
C
      Subroutine DFRESTORE(NH,HITS)
C==============================================================
C- 
C-  Purpose and methods:
C-
C-  Restores vital information about partially fitted tracks
C-  previously stored by routine DFSAVE.
C-  It should be called after a call to DFITER, (and in case
C-  something BAD happened) if one wants to restore the 
C-  previous situation.
C-  By default it restores the TRACK PARAMETERS, the STEP LENGTH at 1st hit
C-  the drift dist. of hit NH and its error, the guessed chisq DFCHIN,
C-  the pointer to the hit contributing most to chisq NDFMCH, and the 
C-  maximum individual chisq DFMCH, the error flag NDFERR and mult. scatt.
C-  parameters DFPMS
C-
C-
C-  Input parameters
C-
C-  Integer NH     The current hit, whose D.D. and err. is to be restored 
C-
C-  Logical HITS   If .TRUE. restore the hits chain NDF and
C-                 all related info (i.e. vectors DFD,DFE,DFL,DFS)
C-                 NFITPOS and NFITNEG and all mult. scattering info:
C-                 NDFDIM,MDF,NDFMS,DFEMS.
C-
C-  N.B. 
C-         DFRESTORE DOES NOT DEAL WITH DRIFT DISTANCE IN DHRE2 !!!
C-
C-
C-  Created: Feb 1998 F. Ambrosino
C-
C===============================================================
$$IMPLICIT
$$INCLUDE 'K$ITRK:CDFWORK.INC'
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$ITRK:DFSAV.INC'

      INTEGER NH,M,K,K_OLD
      LOGICAL HITS

      IF(HITS) THEN
         IF(.NOT. SAVED_HITS) THEN
            CALL ERLOGR('DFRESTORE',ERWARN,0,0,
     &           'Tried to restore hits, but they were not saved !!')
            GO TO 100
         ENDIF

         IF(NHITSAVE.NE.(NPOSSAVE+NNEGSAVE)) THEN
            CALL ERLOGR('DFRESTORE',ERWARN,0,0,
     &           'Inconsistent number of hits from DFSAVE!?!')
            GO TO 100
         ENDIF

         NDF1 = NDF1SAVE
         NDFL = NDFLSAVE
         NDFDIM = NDFDIMSAVE
         K    = NDF1

         DO WHILE(K.GT.0)
            NDF(K) = NDFSAVE(K)
            DFD(K) = DFDSAVE(K)
            DFE(K) = DFERRSAVE(K)
            DFS(K) = DFSSAVE(K)
            DFL(K) = DFLSAVE(K)
            MDF(K) = MDFSAVE(K)
            K = NDFSAVE(K)
         ENDDO

         NFITPOS = NPOSSAVE  
         NFITNEG = NNEGSAVE

         DO M = 2,(NDFDIM-5)
            NDFMS(M) = NDFMSSAVE(M)
            DFEMS(M) = DFEMSSAVE(M)
         ENDDO

      ENDIF

 100  Continue

      IF(.NOT. SAVED_PARA) THEN
         CALL ERLOGR('DFRESTORE',ERWARN,0,0,
     &        'Tried to restore params, but were not saved !!')
         GO TO 200
      ENDIF
      NDFERR  = NDFERRSAVE
      NDFMCH  = NMCHSAVE 
      DFMCH   = DFMCHSAVE 
      DFKURV  = DFSAV( 1)
      DFCTGT  = DFSAV( 2)
      DFSTHE  = DFSAV( 3)
      DFPHI   = DFSAV( 4)
      DFX(NDF1)  = DFSAV( 5)
      DFY(NDF1)  = DFSAV( 6)
      DFZ(NDF1)  = DFSAV( 7)
      DFPX(NDF1) = DFSAV( 8)
      DFPY(NDF1) = DFSAV( 9)
      DFPZ(NDF1) = DFSAV(10)
      DFCHIN  = DFSAV(11)
      DFD(NH) = DFSAV(12)
      DFE(NH) = DFSAV(13)
      DFS(NDF1) = DFSAV(14)

C------ Multiple scattering

         DO M = 2,(NDFDIM-5)
            DFPMS(M) = DFPMSSAVE(M)
         ENDDO     

 200  Continue

      Return
      End
C
C*DK DTFSKILL
C
C====================================================================
	SUBROUTINE DTFSKILL(TRKMERGE)
C====================================================================
C
C	DESCRIPTION:
C      	===========
C BY comparing the chi2 of the new trk with the mean of old ones it kill
c the worse(s). WARNING:not always the trk is fitted so DTFSKILL
c can return without  any action
C
$$implicit

c------ Include Files ----

$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$INC:ERLEVL.INC'
$$include 'K$INC:OFERCO.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$include 'K$ITRK:DTFS.INC'
$$include 'K$ITRK:STUMPCOM.INC'  

c------ External Declaration -----
	
	integer BLOCAT,MDROP
	
c------ Local Declaration --------

	integer STATUS,ISTAT,TRKMERGE
	integer IND_DTM,INDDAT_DTM,IC,BESTICOP
	integer IND_DTF1,IND_DTF2
	integer TRK1,TRK2,INDDAT_DTF1,INDDAT_DTF2
	integer POINT_TRM,POINT_TR1,POINT_TR2
	integer NPOS_TRM,NNEG_TRM,NHIT_TRM
	integer NPOS_TR1,NNEG_TR1,NHIT_TR1
	integer NPOS_TR2,NNEG_TR2,NHIT_TR2
	real 	CHI2_TRM,CHI2_TR1,CHI2_TR2,CHI2_MEAN
	logical	TRM_KILL,TRM_KILL0,HIT_CUT
	real PTTRI,COTTRI,PHITRI,PTTRJ,COTTRJ,PHITRJ
	real PXTRI,PYTRI,PZTRI,PXTRJ,PYTRJ,PZTRJ
	real ENI,ENJ,PIJ2,KLMASS,MPI
	data MPI/139.570/ 

C------ Start of code ------

	STATUS = OFSUCC

c------ Firstly check if the DTFS TRK existed 
c------ (or existed only the DPRS)

	ISTAT = BLOCAT (IW,'DTFS',TRKMERGE,IND_DTM,INDDAT_DTM)
	if (ISTAT.ne.YESUCC) then !this could happen
	  goto 900
        endif
	do IC=1,NCOP	
	 if(TRKMERGE.eq.BNKS(IC)) then
	   BESTICOP =IC
	 endif 
	enddo 
	TRK1=FIRSTUMP(BESTICOP)
	TRK2=SECSTUMP(BESTICOP)
	ISTAT = BLOCAT (IW,'DTFS',TRK1,IND_DTF1,INDDAT_DTF1)
	if (ISTAT.ne.YESUCC) then
          call ERLOGR ('DTFSKILL',ERWARN,0,0,'Cannot find DTFS')
	  goto 990
        endif
	ISTAT = BLOCAT (IW,'DTFS',TRK2,IND_DTF2,INDDAT_DTF2)
	if (ISTAT.ne.YESUCC) then
          call ERLOGR ('DTFSKILL',ERWARN,0,0,'Cannot find DTFS')
	  goto 990
        endif
		
	POINT_TRM=INDDAT_DTM+IW(INDDAT_DTM+DTFHDS) 
	POINT_TR1=INDDAT_DTF1+IW(INDDAT_DTF1+DTFHDS) 
	POINT_TR2=INDDAT_DTF2+IW(INDDAT_DTF2+DTFHDS) 

C---- Compare the CHI2-------------------------------
	
C First Merged TRK

	  NPOS_TRM    = IW(POINT_TRM+DTFNHF)/10000
	  NNEG_TRM    = MOD(IW(POINT_TRM+DTFNHF),10000)
	  NHIT_TRM    = NPOS_TRM + NNEG_TRM 
	  CHI2_TRM    = RW(POINT_TRM+DTFCHI)/(NHIT_TRM-5)

C Then First TRK

	  NPOS_TR1    = IW(POINT_TR1+DTFNHF)/10000
	  NNEG_TR1    = MOD(IW(POINT_TR1+DTFNHF),10000)
	  NHIT_TR1    = NPOS_TR1 + NNEG_TR1 
	  CHI2_TR1    = RW(POINT_TR1+DTFCHI)/(NHIT_TR1-5)

C Then Second TRK

	  NPOS_TR2    = IW(POINT_TR2+DTFNHF)/10000
	  NNEG_TR2    = MOD(IW(POINT_TR2+DTFNHF),10000)
	  NHIT_TR2    = NPOS_TR2 + NNEG_TR2 
	  CHI2_TR2    = RW(POINT_TR2+DTFCHI)/(NHIT_TR2-5)

	 CHI2_MEAN=0.5*(CHI2_TR1+CHI2_TR2)			
	 if(chi2_mean.lt.0.000001) chi2_mean = 0.000001
	
      	 TRM_KILL0=abs((CHI2_TRM-CHI2_MEAN)/CHI2_MEAN).gt.0.6

	 HIT_CUT = (NHIT_TR1+  NHIT_TR2 - NHIT_TRM) .gt. 20 
	 TRM_KILL = TRM_KILL0 .or.  HIT_CUT

	 if(TRM_KILL) then ! kill new merged Trk	
	   STATUS = MDROP(IW,'DTFS',TRKMERGE)  		
	   if (IW(2).ne.YESUCC) then	
             call ERLOGR ('DTFSKILL',ERWARN,0,0,'Cannot drop DTFS')
	     goto 990
           endif
	 else	
	 
C Store also the #dtfs of joined tracks 

 	   IW(POINT_TRM+DTFVMT) = TRK1
           IW(POINT_TRM+DTFVDT) = TRK2	

	 RW(POINT_TRM+DTFCHM)=CHI2_MEAN


C ALSO for Monte Carlo store the number of hits of the two tracks
C
	   IW(POINT_TRM+DTFCEN) = NHIT_TR1+NHIT_TR2
  

           STATUS = MDROP(IW,'DTFS',TRK1)  	   
	   if (IW(2).ne.YESUCC) then	
             call ERLOGR ('DTFSKILL',ERWARN,0,0,'Cannot drop DTFS')
	     goto 990
           endif
           STATUS = MDROP(IW,'DTFS',TRK2)  	   
	   if (IW(2).ne.YESUCC) then	
             call ERLOGR ('DTFSKILL',ERWARN,0,0,'Cannot drop DTFS')
	     goto 990
           endif
	 endif
 900	continue
	goto 999

 990 	continue 
	STATUS=OFFAIL

 999  	return
	end

C	
C*DK HITCODE
C
C=======================================================================
C
      SUBROUTINE HITCODE()
$$IMPLICIT

C       Global Declarations:-
C       =====================

$$INCLUDE 'C$INC:JOBSTA.INC'
$$INCLUDE 'C$INC:BPOYBS.INC'
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'YBOS$LIBRARY:BNKTYP.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:CCONST.INC'
$$INCLUDE 'K$ITRK:CTIDRI.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'  
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'

      INTEGER BLOCAT
      INTEGER STATUS,INDR,INDDATR,DHRENCO,IND,
     +        IDHI,IDDATHI,DHIENCO,DHIENRO,
     +        IDKI,INDKATH,
     +        HITG,IPOINT,IPTYPE,IPCODE(50),
     +        PACODE,JCODE,IWIRE,N,JJ
      INTEGER IFLAGCHI
      INTEGER MUP,MUM,PIONP,PIONM
      COMMON/CHIINIT/IPTYPE(MXHIT),PACODE 
      COMMON/CHIINIT2/MUP,MUM,PIONP,PIONM
      COMMON/IFCHI/IFLAGCHI

      IFLAGCHI=0
      CALL VZERO(IPTYPE,MXHIT)
      CALL VZERO(IPCODE,50)

*  dhit bank (IDHI,IDDATHI)

      STATUS=BLOCAT(IW,'DHIT',1,IDHI,IDDATHI)
      IF (STATUS.NE.YESUCC) RETURN
      IDHI=IDDATHI+IW(IDDATHI+DHIHDS)
      DHIENCO=IW(IDDATHI+DHINCO)
      DHIENRO=IW(IDDATHI+DHINRO) 
 
        N = NDF1
        DO WHILE (N.GT.0)
          IF (LDFL(N).GT.0)  THEN

             IWIRE=IABS(IW(JDPRS1+DPRLWI*(N-1)+DPRIWI))
             IF (IWIRE.GT.10000) THEN
                IFLAGCHI=1
                WRITE(6,*)'strange value of iwire'
                WRITE(6,*)'iwire=',iwire
                RETURN
              ENDIF

             IPTYPE(N)=IW(IDHI+(IWIRE-1)*DHIENCO+DHIPTY) 
             IPCODE(IPTYPE(N))=IPCODE(IPTYPE(N))+1
          
          ENDIF
          N = NDF(N)
        ENDDO

        JCODE=0
        PACODE=0
        DO JJ=1,50
           IF (IPCODE(JJ).GE.JCODE) THEN
              JCODE=IPCODE(JJ)
              PACODE=JJ
           ENDIF
        ENDDO
             
        MUP=0
        MUM=0
        PIONP=0
        PIONM=0
        
        DO JJ=1,50
           IF (IPCODE(JJ).GT.0) THEN
              IF (JJ.EQ.5) THEN
                 MUP=IPCODE(JJ)
              ENDIF
              IF (JJ.EQ.6) THEN
                 MUM=IPCODE(JJ)
              ENDIF
              IF (JJ.EQ.8) THEN
                 PIONP=IPCODE(JJ)
              ENDIF
              IF (JJ.EQ.9) THEN
                 PIONM=IPCODE(JJ)
              ENDIF
           ENDIF
        ENDDO     

        END
C==========================================================================
      SUBROUTINE DFTWOPR(KINK_POS,NTRACK)
C========================================================================
C
C     INPUT  PARAMETERS:        
C
C     Int KINK_POS               ! Guessed position of kink in the track 
C                                
C  
C     Int NTRACK                 ! Number of DPRS bank of the track
C
C
C     OUTPUT PARAMETERS:         None
C
C
C======================================================================
C=
C=   Purpose and Methods : This routine splits one track, with kink,
C=                         (as signaled by DFKINK) in two separate tracks, 
C=                         then writes two new DPRS bank with version number   
C=                         BNKVRS = 10 + NTRACK (so to keep track of their
C=                         origin)
C=
C=   Created   15-4-1998  F.Ambrosino C. Di Donato
C=========================================================================
C
C
$$IMPLICIT
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$INC:BPOYBS.INC'
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$INC:OFERCO.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$ITRK:MCKINE.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'
C
$$INCLUDE 'K$ITRK:CFLAGS.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'
C
$$INCLUDE 'C$INC:jobsta.INC'
C
C
C
C
C----------------  COMMON SPLITTED TRACK PARAMETERS  ------------------------
C
      INTEGER MAX_PAR
      PARAMETER (MAX_PAR=9)
      INTEGER MAX_HITS
      PARAMETER (MAX_HITS=250)
C
      REAL             PAR1
      INTEGER          NPOS_1, NNEG_1, NHITS1
      REAL             PAR2
      INTEGER          NPOS_2, NNEG_2, NHITS2
      REAL             STEPS
C
      COMMON /PAR/ PAR1(MAX_PAR), NPOS_1, NNEG_1, NHITS1, 
     +             PAR2(MAX_PAR), NPOS_2, NNEG_2, NHITS2,
     +             STEPS(MAX_HITS)
C-----------------------------------------------------------------------
C
C
C------------------------------------------External functions
      INTEGER BTYMKG, BLOCAT, BIGEST
C
C------------------------------------------Local Declarations
      INTEGER STATUS
      INTEGER KINK_POS, NTRACK
      INTEGER IND_DHRE, INDAT_DHRE
      INTEGER IND_DPRS, INDAT_DPRS
      INTEGER NUM_ROW, NUM_DATA_ROW
      INTEGER MAXTRACK, NHITSP
      INTEGER NEW1, NEW2
      INTEGER IND1, INDAT1, IND2, INDAT2
      INTEGER B1NKSIZ, B2NKSIZ
      INTEGER DHRE_ADDR, LINK
      INTEGER IOFFSET, IOFFSET2
C
      INTEGER I, II
C
      CHARACTER*36 B1NKTYP
      DATA B1NKTYP/'2I4,9R4,2I4,R4,2I4,2R4,I4,XYX(I4,R4)'/
C
      CHARACTER*36 B2NKTYP
      DATA B2NKTYP/'2I4,9R4,2I4,R4,2I4,2R4,I4,XXY(I4,R4)'/
C
C
C
C
C--------------------------------Executable code ---------------------

C
C Inizialization
C
     I  = 0
      II = 0
      NUM_ROW       = 0
      NUM_DATA_ROW  = 0
      NEW1 = 0
      NEW2 = 0
C
C  ======  Find the max bank number of DPRS chain
C
      STATUS     = BIGEST(IW,'DPRS',MAXTRACK)
C
      NEW1 = MAXTRACK + 1
      NEW2 = MAXTRACK + 2
C
C
C  ======= Create the new DPRS bank for the daughter tracks
C
C
      WRITE (B1NKTYP(27:29),'(I3)') NHITS1
      WRITE (B2NKTYP(27:29),'(I3)') NHITS2
C
      STATUS = BTYMKG(IW,'DPRS',NEW1,
     +                    B1NKTYP,B1NKSIZ,IND1,INDAT1)
      IF (STATUS.NE.YESUCC) THEN
         CALL ERLOGR('DSPLIT',ERWARN,0,STATUS,
     +        'Error creating new bank DPRS #1')
         GOTO 999
      ENDIF
C
      STATUS = BTYMKG(IW,'DPRS',NEW2,
     +                    B2NKTYP,B2NKSIZ,IND2,INDAT2)
      IF (STATUS.NE.YESUCC) THEN
         CALL ERLOGR('DSPLIT',ERWARN,0,STATUS,
     +        'Error creating new bank DPRS #2')
         GOTO 999
      ENDIF
C 
C
C
C=====     Locate DHRE 2 bank
C
      STATUS     = BLOCAT(IW,'DHRE',2,IND_DHRE
     &               ,INDAT_DHRE)
      IF(STATUS.NE.YESUCC) go to 999

      NUM_ROW      =  IW(INDAT_DHRE +DHRNRO)
      NUM_DATA_ROW =  IW(INDAT_DHRE +DHRNCO)
      INDAT_DHRE   =  INDAT_DHRE + IW(INDAT_DHRE+DHRHDS)
C
C========  Locate the DPRS bank to split
C
      STATUS     = BLOCAT(IW,'DPRS',NTRACK,IND_DPRS
     &               ,INDAT_DPRS)
      IF(STATUS.NE.YESUCC) go to 999

      INDAT_DPRS = INDAT_DPRS + IW(INDAT_DPRS + DPRHDS)
      IND_DPRS   = INDAT_DPRS + DPRCEN
      NHITSP     = IW(INDAT_DPRS+DPRPOS) + IW(INDAT_DPRS+DPRNEG)
C
C=================================================================
C     Fill new DPRS banks => from DFKINK parameters vectors 
C                            and related info
C
C     NEW DPRS #1----------------------------------------------------
C
      IW(INDAT1+DPRHDS) = 2
      IW(INDAT1+DPRVRN) = 10+NTRACK
      INDAT1 = INDAT1 + IW(INDAT1+DPRHDS)
      RW(INDAT1+DPRXCO) = PAR1(1)
      RW(INDAT1+DPRYCO) = PAR1(2)
      RW(INDAT1+DPRZCO) = PAR1(3)
      RW(INDAT1+DPRXLS) = PAR1(4)
      RW(INDAT1+DPRYLS) = PAR1(5)
      RW(INDAT1+DPRZLS) = PAR1(6)
      RW(INDAT1+DPRCUR) = PAR1(7)
      RW(INDAT1+DPRPHI) = PAR1(8)
      RW(INDAT1+DPRCTT) = PAR1(9)
      RW(INDAT1+DPRQUA) = 0.
      IW(INDAT1+DPRPOK) = 3
      IW(INDAT1+DPRPOS) = NPOS_1  
      IW(INDAT1+DPRNEG) = NNEG_1
      IW(INDAT1+DPRLRG) = 0
      RW(INDAT1+DPRPHF) = 0.
      RW(INDAT1+DPRPHL) = 0. 
C
C
      IW(INDAT1+DPRCEN) = IW(INDAT_DPRS+DPRCEN) 
      IND1 = INDAT1 + DPRCEN
C     
C     Fills Variable length part of the Bank  
C     
      DO I = 1,NHITS1
         IOFFSET = (I-1)*DPRLWI
         DHRE_ADDR = IABS(IW(IND_DPRS+IOFFSET+DPRIWI))
         IW(IND1+IOFFSET+DPRIWI) = DHRE_ADDR
         RW(IND1+IOFFSET+DPRWTR) = STEPS(I)
C
C     Fills DHRE2 link database with the new DPRS bank number
C     DHRE_ADDR is number of the hit in DHRE2 bank
C
         IOFFSET = (DHRE_ADDR-1)*NUM_DATA_ROW
         IW(INDAT_DHRE+IOFFSET+DHRTRN) = NEW1
      ENDDO
C
C
C     DPRS BANK #2--------------------------------------------------------
C
      IW(INDAT2+DPRHDS) = 2
      IW(INDAT2+DPRVRN) = 10+NTRACK
      INDAT2 = INDAT2 + IW(INDAT2+DPRHDS)
      RW(INDAT2+DPRXCO) = PAR2(1)
      RW(INDAT2+DPRYCO) = PAR2(2)
      RW(INDAT2+DPRZCO) = PAR2(3)
      RW(INDAT2+DPRXLS) = PAR2(4)
      RW(INDAT2+DPRYLS) = PAR2(5)
      RW(INDAT2+DPRZLS) = PAR2(6)
      RW(INDAT2+DPRCUR) = PAR2(7)
      RW(INDAT2+DPRPHI) = PAR2(8)
      RW(INDAT2+DPRCTT) = PAR2(9)
      RW(INDAT2+DPRQUA) = 0.
      IW(INDAT2+DPRPOK) = 3
      IW(INDAT2+DPRPOS) = NPOS_2
      IW(INDAT2+DPRNEG) = NNEG_2
      IW(INDAT2+DPRLRG) = 0
      RW(INDAT2+DPRPHF) = 0.
      RW(INDAT2+DPRPHL) = 0. 
C
C
      IW(INDAT2+DPRCEN) = IW(INDAT_DPRS+DPRCEN) 
      IND2 = INDAT2 + DPRCEN
C     
C     Fills Variable length part of the Bank  
C     
      DO I = 1,NHITS2
         IOFFSET = (I+NHITS1-1)*DPRLWI
         IOFFSET2 = (I-1)*DPRLWI
         DHRE_ADDR = IABS(IW(IND_DPRS+IOFFSET+DPRIWI))
         IW(IND2+IOFFSET2+DPRIWI) = DHRE_ADDR
         RW(IND2+IOFFSET2+DPRWTR) = STEPS(I+NHITS1)
C     
C     Fills DHRE2 link database with the new DPRS bank number
C     DHRE_ADDR is number of the hit in DHRE2 bank
C     
         IOFFSET = (DHRE_ADDR-1)*NUM_DATA_ROW
         IW(INDAT_DHRE+IOFFSET+DHRTRN) = NEW2
      ENDDO
C     
C==================================================================
C      
C     Purge track candidate number-link (DHRTRN)
C     for the ''old'' track (useful to set free the hits added to  
C     the old track and give the new tracks a chance to get them)
C
      DO I = 1, NUM_ROW
         IOFFSET = (I-1)*NUM_DATA_ROW
         LINK = IW(INDAT_DHRE + IOFFSET + DHRTRN)
         IF(LINK.EQ.NTRACK) THEN
            IW(INDAT_DHRE + IOFFSET + DHRTRN) = 0
         ENDIF
      ENDDO
C
C-------------------------------------------------------------------
C
 999  CONTINUE

      RETURN
      END
C
C========================================================================
      SUBROUTINE DFSPLIT
C========================================================================
$$IMPLICIT
C------------------------------------------------------------------------
C-
C-   Purpose and Methods : This routine is intended to perform the final
C-                         check wether a track is to be splitted or not
C-                         The real decision, however is taken in routine
C-                         DFCOMPARE, and DFSPLIT makes all needed operations
C-                         to clean DPRS and DTFS bank chains
C-
C-    Author: F. Ambrosino C. Di Donato
C     =======
C-                
C-    created 17 4 98   
C-    updated 16 9 98
C----------------------------------------------------------------------
C
C       Global Declarations:-
C       =====================
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:CFLAGS.INC'
$$INCLUDE 'K$ITRK:DTFS.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
C
C
C        External Functions
C        ==================
C
      INTEGER BLOCAT, BNUMB, BDATA, BNEXT, MDROP
C
C       Local Declarations:-
C       ====================
C
C
      INTEGER STATUS 
      INTEGER IND_DHRE, INDAT_DHRE, DHRE_DATA
      INTEGER STATUS_DTFS, IND_DTFS, INDAT_DTFS
      INTEGER STATUS_DPRS, IND_DPRS, INDAT_DPRS
      INTEGER VERSION, IMOTHER, IDAUGHT1, IDAUGHT2
C

      INTEGER IND_MOT, INDAT_MOT, NHITS
      INTEGER IOFFSET, DHRE_ADDR, DHRE_HITS, LINK
C
      LOGICAL KEEPMOTHER
      LOGICAL KILL_D1,KILL_D2,CLEAN

C
C
      INTEGER I
C
C
      IF(.NOT. KINK_RECO) goto 1000
C
C     Look for kink-track and splitted-track
C     If bank Version Number in DPRS bank is >10,
C     this is a stump of a splitted track; the mother
C     bank number is (bank Version number - 10)
C
C
      IMOTHER = 0
      IDAUGHT1 = 0
      IDAUGHT2 = 0
      Keepmother = .false.
      KILL_D1  = .FALSE.
      KILL_D2  = .FALSE.
      CLEAN    = .FALSE.
C      
C
C
      STATUS = BLOCAT(IW,'DHRE',2,IND_DHRE,INDAT_DHRE)
      IF(STATUS.NE.YESUCC) THEN
         Call ERLOGR('DFSPLIT',ERWARN,0,0,
     &             'DHRE bank NOT FOUND!!!')
         GO TO 1000
      ENDIF
C
      DHRE_DATA = IW(INDAT_DHRE + DHRNCO)
      DHRE_HITS = IW(INDAT_DHRE + DHRNRO)
      IND_DHRE = INDAT_DHRE + IW(INDAT_DHRE + DHRHDS)
C
      STATUS_DPRS = BLOCAT(IW,'DPRS',-1,IND_DPRS,INDAT_DPRS)
      DO WHILE (IND_DPRS.GT.0)
         VERSION = IW(INDAT_DPRS + DPRVRN)
         IF (VERSION.lt.10) then
            STATUS = BNEXT(IW,IND_DPRS,IND_DPRS)
            go to 999
         ENDIF
         IMOTHER = VERSION - 10
C
C--------------------------------This bank SHOULD exist, but in case the
C                                mother is itself daughter of another track
C                                it may have been erased : in such cases
C                                we just drop all the 'discendence'
C
c     
         STATUS = BLOCAT(IW,'DPRS',IMOTHER,IND_MOT,INDAT_MOT)
         IF(STATUS.NE.YESUCC) THEN
            KEEPMOTHER = .TRUE.
            STATUS = BNUMB(IW,IND_DPRS,IDAUGHT1)
            STATUS_DPRS=BNEXT(IW,IND_DPRS,IND_DPRS)
            STATUS = BNUMB(IW,IND_DPRS,IDAUGHT2)
            GO TO 777
         ENDIF
C
C--------------------------IDAUGHT1 is the first daughter bank number
C
         STATUS = BNUMB(IW,IND_DPRS,IDAUGHT1)
C
C-------------------------This is the second daughter, this bank MUST exist
C
         STATUS_DPRS=BNEXT(IW,IND_DPRS,IND_DPRS)
         IF(IND_DPRS.EQ.0) THEN
            Call Erlogr('DFSPLIT',erwarn,0,0,
     &           'Second daughter not found !!!')
            keepmother = .true.
            Go to 777
         ENDIF
         STATUS_DPRS = BDATA(IW,IND_DPRS,INDAT_DPRS)
         IF(IW(INDAT_DPRS+DPRVRN).NE.VERSION) THEN
            Call Erlogr('DFSPLIT',erwarn,0,0,
     &           'Second daughter wrong link !!!')
            keepmother = .true.
            Go to 777
         ENDIF 
C--------------------------IDAUGHT2 is the second daughter bank number
C
         STATUS = BNUMB(IW,IND_DPRS,IDAUGHT2)
C-------------------------------------------------------
C   
C  Now we have links to mother track and to both daughters and we call
C     DFCOMPARE to decide wether the mother bank must be kept (and the
c     daughters killed) or vice-versa
C--------------------------------------------------------
         Call DFCOMPARE(IMOTHER,IDAUGHT1,IDAUGHT2,KEEPMOTHER)
C
 777     CONTINUE

CC
C This MUST be put here to be safe, to locate next bank the previous
C must exist, and maybe we are going to kill last DPRS bank located....
C 
         STATUS = BNEXT(IW,IND_DPRS,IND_DPRS)
C
C
         IF(KEEPMOTHER) THEN
C
C-----------------------------------Kill daughters DPRS banks...
C
            STATUS = MDROP(IW,'DPRS',IDAUGHT1)
            STATUS = MDROP(IW,'DPRS',IDAUGHT2)
            KILL_D1 = .TRUE.
            KILL_D2 = .TRUE.
C     
C------------------------------------..and then corresponding DTFS banks
C                                    if they exist....

            STATUS_DTFS = BLOCAT(IW,'DTFS',IDAUGHT1
     &           ,IND_DTFS,INDAT_DTFS)
            IF(STATUS_DTFS.EQ.YESUCC) THEN
               STATUS = MDROP(IW,'DTFS',IDAUGHT1)
            ENDIF
C
            STATUS_DTFS = BLOCAT(IW,'DTFS',IDAUGHT2
     &           ,IND_DTFS,INDAT_DTFS)
            IF(STATUS_DTFS.EQ.YESUCC) THEN
               STATUS = MDROP(IW,'DTFS',IDAUGHT2)
            ENDIF
C------------------------------------...finally restore DHRE2 original links
C
            STATUS = BLOCAT(IW,'DPRS',IMOTHER,IND_MOT,INDAT_MOT)
            IF(STATUS.ne.YESUCC) THEN
               Call erlogr('DFSPLIT',erwarn,0,0,
     &              'DPRS mother bank not found ?!?!')
               goto 999
            ENDIF
            IND_MOT = INDAT_MOT + IW(INDAT_MOT + DPRHDS)
            NHITS = IW(IND_MOT+DPRPOS)+IW(IND_MOT+DPRNEG)
            IND_MOT = IND_MOT + DPRCEN
            DO I = 1,NHITS
               IOFFSET = (I-1)*DPRLWI
               DHRE_ADDR = IABS(IW(IND_MOT+IOFFSET+DPRIWI))
               IOFFSET = (DHRE_ADDR-1)*DHRE_DATA
               IW(IND_DHRE+IOFFSET+DHRTRN) = IMOTHER               
            ENDDO
               
         ELSE
C------------------------------Kill mother banks
C
            STATUS = MDROP(IW,'DPRS',IMOTHER)
            STATUS_DTFS = BLOCAT(IW,'DTFS',IMOTHER
     &           ,IND_DTFS,INDAT_DTFS)
            IF(STATUS_DTFS.EQ.YESUCC) THEN
               STATUS = MDROP(IW,'DTFS',IMOTHER)
            ENDIF
C     
C--------------------------..and also the daughters if have not 
C                          been fitted !!!
C
C
            STATUS_DTFS = BLOCAT(IW,'DTFS',IDAUGHT1
     &           ,IND_DTFS,INDAT_DTFS)
            IF(STATUS_DTFS.NE.YESUCC) THEN
               STATUS = MDROP(IW,'DPRS',IDAUGHT1)
               KILL_D1 = .true.
            ENDIF
C
            STATUS_DTFS = BLOCAT(IW,'DTFS',IDAUGHT2
     &           ,IND_DTFS,INDAT_DTFS)
            IF(STATUS_DTFS.NE.YESUCC) THEN
               STATUS = MDROP(IW,'DPRS',IDAUGHT2)
               KILL_D2 = .TRUE.
C               IF(KILL_D1) then
C                  Call erlogr('DFSPLIT',erwarn,0,0,
C     &                 'Both daughters killed')
C               ENDIF
            ENDIF
         ENDIF
C     
C-------------------------FINALLY CLEAN DHRE2 LINKS TO KILLED DAUGHTERS
C
         IF(KILL_D1.OR.KILL_D2) THEN
            DO I = 1,DHRE_HITS
               IOFFSET = (I-1)*DHRE_DATA
               LINK = IW(IND_DHRE + IOFFSET + DHRTRN)
               CLEAN = (KILL_D1.AND.(LINK.EQ.IDAUGHT1)).OR.
     &                 (KILL_D2.AND.(LINK.EQ.IDAUGHT2))
               IF(CLEAN) THEN
                  IW(IND_DHRE + IOFFSET + DHRTRN) = 0
               ENDIF
            ENDDO
         ENDIF
C
C     
 999    Continue    
        STATUS_DPRS=BDATA(IW,IND_DPRS,INDAT_DPRS)
C
      ENDDO
C
C
C
 1000 CONTINUE
      RETURN 
      END
C

C===================================================================
      SUBROUTINE DFCOMPARE(IMOTHER,IDAUGHT1,IDAUGHT2,KEEPMOTHER)
C===================================================================
$$IMPLICIT
C----------------------------------------------------------------------
C-
C-   Purpose and Methods : This routine is intended to take the final decision
C-                         wether a track which has been splitted in two 
C-                         has to be kept (and its daughters killed) or 
C-                         vice-versa.
C-          
C-    Input parameters :
C-
C-      Int IMOTHER          # of Mother track's DPRS bank
C-      Int Idaught1         # of 1st daughter track's DPRS bank
C-      Int Idaught2         # of 2nd daughter track's DPRS bank
C-
C-    Output parameters :
C-
C-      Logical keepmother      If .true. keep mother track
C-
C-
C-    Author: F. Ambrosino C. Di Donato
C     =======
C-                
C-    created 17 4 98   
C-    updated 16 9 98
C-    updated 4 12 98   (New cuts definition) F. A.
C----------------------------------------------------------------------
C
C     Global Declarations:-
C     =====================
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$ITRK:DTFS.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
C
C     External Functions:-
C     ===================
C
      INTEGER BLOCAT
C
C     Local Declarations:-
C     ====================
C
      INTEGER IMOTHER
     &        ,idaught1
     &        ,idaught2
C
      LOGICAL KEEPMOTHER
C
      INTEGER STATUS
      INTEGER IND_MOTH, INDAT_MOTH
      INTEGER IND_DTFS1, INDAT_DTFS1
      INTEGER IND_DTFS2, INDAT_DTFS2
C
      REAL    CHIMOTHER, CHIDAUGHT1, CHIDAUGHT2,BESTCHI
      REAL    CHIM1, CHIM2
      REAL    TF_CURV, TF_CTGT, TF_PHI
      REAL    PX1,PY1,PZ1,PX2,PY2,PZ2,P1,P2,DOT,PT1,PT2
      REAL    COSTHETA,DELTAPT,DELTAPZ
      REAL    PXMOT,PYMOT,PZMOT
      REAL    FRAC,FRAC2
      INTEGER MAXHITS,MINHITS
      INTEGER CODEH,CODEH1,CODEH2
      INTEGER NHITPOS, NHITNEG
      INTEGER NHITPOS1, NHITNEG1
      INTEGER NHITPOS2, NHITNEG2
      INTEGER NHITMOT,NHIT1,NHIT2
C
      LOGICAL FITD1,FITD2,FITMOT
      LOGICAL ONLY_1_FITD,ONLY_2_FITD,BOTH_FITD,NO_FITD
      LOGICAL CUT1,CUT2,CUT3,CUT4,CUT5,CUT6
C
C----------------------------------------CUTS
      INTEGER DIFFHIT
      REAL    MINCHI1,MINCHIDIFF1
      PARAMETER(DIFFHIT=5)
      PARAMETER(MINCHI1=9.)
      PARAMETER(MINCHIDIFF1=6.)

      REAL    MINCOSTHETA,MAXDPT,MAXDPZ,MAXFRAC,MINCHIFRAC
      PARAMETER(MINCOSTHETA=0.9975)
      PARAMETER(MAXDPT=5.)
      PARAMETER(MAXDPZ=5.)
      PARAMETER(MAXFRAC=-0.26)
      PARAMETER(MINCHIFRAC=0.16)

C
C--------------------------------------INITIALIZATIONS
      FITD1        = .FALSE.
      FITD2        = .FALSE.
      FITMOT       = .FALSE.
      ONLY_1_FITD  = .FALSE.
      ONLY_2_FITD  = .FALSE.
      BOTH_FITD    = .FALSE.
      NO_FITD      = .FALSE.
C
C
C
C---------------------------------LOCATE BANKS (IF THEY EXIST!)
C
      STATUS = BLOCAT(IW,'DTFS',IMOTHER,IND_MOTH,INDAT_MOTH)
      IF(STATUS.EQ.YESUCC) THEN
         FITMOT = .TRUE.
         INDAT_MOTH = INDAT_MOTH + IW(INDAT_MOTH+DTFHDS)
         CHIMOTHER  = RW(INDAT_MOTH+DTFCHI)
         TF_CURV    = RW(INDAT_MOTH+DTFCUR)
         TF_PHI     = RW(INDAT_MOTH+DTFPHI)
         TF_CTGT    = RW(INDAT_MOTH+DTFCTT)
         PXMOT  = (1000./ABS(TF_CURV))
     &                              *COS(TF_PHI)
         PYMOT  = (1000./ABS(TF_CURV))
     &                              *SIN(TF_PHI)
         PZMOT  = (1000./ABS(TF_CURV))
     &                              *TF_CTGT

         CODEH   = IW(INDAT_MOTH+DTFNHF)
         NHITPOS = (CODEH/10000)
         NHITNEG = (CODEH-NHITPOS*10000)
         NHITMOT = NHITPOS + NHITNEG
         IF(NHITMOT.GT.5) THEN
            CHIMOTHER = CHIMOTHER/FLOAT(NHITMOT - 5)
         ENDIF
      ENDIF
C     
      STATUS = BLOCAT(IW,'DTFS',IDAUGHT1,IND_DTFS1,INDAT_DTFS1)
      IF(STATUS.EQ.YESUCC) THEN
         FITD1 = .TRUE.
         INDAT_DTFS1 = INDAT_DTFS1 + IW(INDAT_DTFS1+DTFHDS)
         CHIDAUGHT1  = RW(INDAT_DTFS1+DTFCHI) 
         TF_CURV    = RW(INDAT_DTFS1+DTFCUR)
         TF_PHI     = RW(INDAT_DTFS1+DTFPHI)
         TF_CTGT    = RW(INDAT_DTFS1+DTFCTT)
         PX1  = (1000./ABS(TF_CURV))
     &                              *COS(TF_PHI)
         PY1  = (1000./ABS(TF_CURV))
     &                              *SIN(TF_PHI)
         PZ1  = (1000./ABS(TF_CURV))
     &                              *TF_CTGT

         CODEH1 = IW(INDAT_DTFS1+DTFNHF)
         NHITPOS1 = (CODEH1/10000)
         NHITNEG1 = (CODEH1-NHITPOS1*10000)
         NHIT1 = NHITPOS1 + NHITNEG1
         IF(NHIT1.GT.5) THEN
            CHIDAUGHT1 = CHIDAUGHT1/FLOAT(NHIT1 - 5)
         ENDIF
      ENDIF
C     
      STATUS = BLOCAT(IW,'DTFS',IDAUGHT2,IND_DTFS2,INDAT_DTFS2)
      IF(STATUS.EQ.YESUCC) THEN
         FITD2 = .TRUE.
         INDAT_DTFS2 = INDAT_DTFS2 + IW(INDAT_DTFS2+DTFHDS)
         CHIDAUGHT2  = RW(INDAT_DTFS2+DTFCHI) 
         TF_CURV    = RW(INDAT_DTFS2+DTFCUR)
         TF_PHI     = RW(INDAT_DTFS2+DTFPHI)
         TF_CTGT    = RW(INDAT_DTFS2+DTFCTT)
         PX2  = (1000./ABS(TF_CURV))
     &                              *COS(TF_PHI)
         PY2  = (1000./ABS(TF_CURV))
     &                              *SIN(TF_PHI)
         PZ2  = (1000./ABS(TF_CURV))
     &                              *TF_CTGT

         CODEH2 = IW(INDAT_DTFS2+DTFNHF)
         NHITPOS2 = (CODEH2/10000)
         NHITNEG2 = (CODEH2-NHITPOS2*10000)
         NHIT2 = NHITPOS2 + NHITNEG2
         IF(NHIT2.GT.5) THEN
            CHIDAUGHT2 = CHIDAUGHT2/FLOAT(NHIT2 - 5)
         ENDIF
      ENDIF
C
      ONLY_1_FITD = (FITD1.AND..NOT.FITD2)
      ONLY_2_FITD = (FITD2.AND..NOT.FITD1)
C
      BOTH_FITD     = FITD1.AND.FITD2
      NO_FITD       = .NOT.FITD1.AND..NOT.FITD2
C
C================================================NOW COMPARING TRACKS
C
      IF(.NOT.FITMOT) THEN
         KEEPMOTHER = .FALSE.
         GO TO 999
      ENDIF
C
      IF(NO_FITD) THEN
         KEEPMOTHER = .TRUE.
         GO TO 999
      ENDIF

C--------------------------------HERE THE CHOICE WAS VERY SIMPLE...
C
C     
C--------------------------------....BUT NOW WE HAVE REALLY TO CHOOSE!

      IF(ONLY_1_FITD) THEN 
         CUT1 = (NHITMOT - NHIT1).GT.DIFFHIT
         CUT2 = CHIDAUGHT1.GT.MINCHI1
         CUT3 = (CHIDAUGHT1 - CHIMOTHER).GT.MINCHIDIFF1
         KEEPMOTHER = CUT1.OR.(CUT2.AND.CUT3)
      ELSEIF(ONLY_2_FITD) THEN 
         CUT1 = (NHITMOT - NHIT2).GT.DIFFHIT
         CUT2 = CHIDAUGHT2.GT.MINCHI1
         CUT3 = (CHIDAUGHT2 - CHIMOTHER).GT.MINCHIDIFF1
         KEEPMOTHER = CUT1.OR.(CUT2.AND.CUT3)
      ELSEIF(BOTH_FITD) THEN
C
         p1  = sqrt((px1**2)+(py1**2)+(pz1**2))
         p2  = sqrt((px2**2)+(py2**2)+(pz2**2))
         dot = (PX1*PX2)+(PY1*PY2)+(PZ1*PZ2)
         COSTHETA = dot/(p1*p2)
         pt1 = sqrt(px1**2+py1**2)
         pt2 = sqrt(px2**2+py2**2)
         DELTAPT = pt1 - pt2
         DELTAPZ = pz1 - pz2
         MAXHITS = MAX(NHIT1,NHIT2)
         MINHITS = MIN(NHIT1,NHIT2)
         BESTCHI = MIN(CHIDAUGHT1,CHIDAUGHT2)
         FRAC    = float(MAXHITS - NHITMOT)/float(NHITMOT)
         FRAC2   = (BESTCHI - CHIMOTHER)/CHIMOTHER
C
         CUT1   = FRAC2.GT.MINCHIFRAC
         CUT2   = FRAC.LT.MAXFRAC
         CUT3   = COSTHETA.GT.MINCOSTHETA
         CUT4   = ABS(DELTAPT).LT.MAXDPT
         CUT5   = ABS(DELTAPZ).LT.MAXDPZ
         CUT6   = (CUT4.AND.CUT5).OR.CUT3
C
         KEEPMOTHER = (CUT1.OR.CUT2).OR.CUT6
C
      ENDIF
C     
 999  CONTINUE
      RETURN
      END
C
C
C
C*DFKINK
C==========================================================================
      SUBROUTINE DFKINK(NTRACK,KINKPOS,KINK_FLAG)
C========================================================================
C
C     INPUT  PARAMETERS:        
C
C   Int ntrack                   ! number of track (= # of DPRS bank)
C
C     OUTPUT PARAMETERS:
C
C   Int   kinkpos                ! kink position from algoritm
C                                ! in PR candidate
C
C   Int   kink_flag              !  0 if there is no kink
C                                ! -1 if there is kink   
C======================================================================
C=
C=   Purpose and Methods : This routine scans the partially fitted
C=                         track 'ntrack' looking for a kink.
C=                         If a 'kink candidate' is found,  the vectors     
C=                         of parameters needed to write the new
C=                         DPRS banks in DFTWOPR are stored in
C=                         common /PAR/.
C=                         In any case the track 'ntrack' is left
C=                         unaffected; decision wether to keep it
C=                         or its daughters is taken later, in routine
C=                         DFSPLIT.
C=                      
C=   Created   7-4-1998  F.Ambrosino C. Di Donato
C=   Updated   8-5-1998  F.Ambrosino C. Di Donato
C=   Updated   10-1998   F.Ambrosino
C-   Updated   4-12-1998 (New cuts definition) F. A.
C=
C=========================================================================
C
C
C            Global Declarations:-
C            ====================
C
$$IMPLICIT
$$INCLUDE 'K$INC:BCS.INC'
$$INCLUDE 'K$INC:BPOYBS.INC'
$$INCLUDE 'K$INC:ERLEVL.INC'
$$INCLUDE 'K$INC:OFERCO.INC'
$$INCLUDE 'YBOS$LIBRARY:ERRCOD.INC'
$$INCLUDE 'K$ITRK:DHRE.INC'
$$INCLUDE 'K$ITRK:DPRS.INC'
$$INCLUDE 'K$ITRK:CDFWORK.INC'
$$INCLUDE 'K$ITRK:CFLAGS.INC'
$$INCLUDE 'K$ITRK:CDFCUT.INC'
$$INCLUDE 'C$INC:jobsta.INC'
$$INCLUDE 'K$ITRK:ctidri.INC'
C
C
C
C
C      External Functions:-
C      ==================
C
      INTEGER BLOCAT
      INTEGER LVMAXA
      REAL    VSUM
C
C      Local Declarations:-
C      ===================
C
C----------------  COMMON FOR NEW TRACKS PARAMETERS  ------------------------
      INTEGER MAX_PAR
      PARAMETER (MAX_PAR=9)
      INTEGER MAX_HITS
      PARAMETER (MAX_HITS=250)
C
      REAL             PAR1
      INTEGER          NPOS_1, NNEG_1, NHITS1
      REAL             PAR2
      INTEGER          NPOS_2, NNEG_2, NHITS2
      REAL             STEPS
C
      COMMON /PAR/ PAR1(MAX_PAR), NPOS_1, NNEG_1, NHITS1,
     +             PAR2(MAX_PAR), NPOS_2, NNEG_2, NHITS2,
     +             STEPS(MAX_HITS)
C-----------------------------------------------------------------------
	INTEGER	 SIGN_SRES(MAX_HITS)
     &		,ZERO_CROSS(MAX_HITS)
     &		,KPOS(MAX_HITS)
     &		,CAND(MAX_HITS)
C
C
        REAL     RES(MAX_HITS)
     &          ,SMOOTHRES(MAX_HITS)
     &		,SPOT_INI(MAX_HITS)
     &		,SPOT_SIZE(MAX_HITS)


      INTEGER NTRACK,KINK_FLAG,KINKPOS
      INTEGER STATUS, IND_DPRS, INDAT_DPRS, I
      INTEGER K_HIT, N , K
C
      REAL CHISQ, SMEAN, RSIGMA, RDEV, AVRES
C
      INTEGER  KINK_FND, N_K, NZERO_CROSS
      REAL sign,fraczero,diffres
C
      INTEGER nsp, maxspotsize, last_cross
      REAL AVSPOTSIZE, AV_GAP
      REAL zero
      INTEGER KKK,NN
      real thisres
      real pvres1, pvres2, nxres1, nxres2
      real presm1, nresm1
      real diff1, diff2
      REAL MAXRES
C
      INTEGER STUMP1, STUMP2, MINSTUMP
C
C
      LOGICAL CONS
      LOGICAL LOG1
      LOGICAL LOG2
C
C---------------------------------------------Cuts definition
      real sigma_min, chi_min,cut_cross
      real cut_spsize, cut_zero, cut_gap
      real sharp
      PARAMETER(SIGMA_MIN = 0.055)
      PARAMETER(CHI_MIN  = 7.0)
      PARAMETER(CUT_CROSS = 0.4)
      PARAMETER(CUT_GAP   = 3)
      PARAMETER(CUT_SPSIZE = 0.17)
      PARAMETER(CUT_ZERO = 20.)
      PARAMETER(SHARP = 0.25)
C-----------------------------------------EXECUTABLE CODE
C
C-----------------------Please let us not split twice!!!-------
C
      STATUS = BLOCAT(IW,'DPRS',NTRACK,IND_DPRS,INDAT_DPRS)
      IF(STATUS.NE.YESUCC) THEN
         CALL ERLOGR('DFKINK',ERWARN,0 ,0
     $        ,'DPRS BANK NOT FOUND ??')
         KINK_FLAG = 0
         RETURN
      ENDIF
C
      IF(IW(INDAT_DPRS+DPRVRN).GT.1) THEN
         KINK_FLAG = 0
         RETURN
      ENDIF
C
C===================================================Inititalization
      KINK_FLAG = 0
      KINKPOS   = 0
      K_HIT     = 0
C
C
C--------------------Fill working vectors 
      N = NDF1
      DO WHILE (N.GT.0)
         k_hit = k_hit + 1
         RES(k_hit)        = DFCH(N)
         N = NDF(N)
C
      ENDDO
C
      CHISQ             = DFCHIN
C===============================================================IS THERE A KINK IN THIS TRACK?
C
C----------------------------------Number of hits 
      KINK_FND = -200
      IF(K_HIT.LT.16) GO TO 999   
      KINK_FND = -300
C----------------------------------Chisq
C
C      IF(CHISQ.LT.CHI_MIN) GO TO 999
      IF(CHISQ/float(k_hit-5).LT.CHI_MIN) GO TO 999
      KINK_FND = -400
C
C---------------------------------- Standard dev. (sigma) of residuals
      rsigma = 0.
      Avres   = VSUM(res,k_hit)/float(k_hit)      
C     
      do i = 1, k_hit
         rdev = (Avres - res(i))**2
         rsigma  = rsigma + rdev
      enddo
      rsigma = sqrt(rsigma/float(k_hit - 1))
      IF(RSIGMA.LT.SIGMA_MIN) GOTO 999  
C      
C
C
C------------------------------------ Smoothing the residuals distribution
C     
      SMEAN = 0.
      do i = 1, k_hit
         if(i.gt.1) then
            SMEAN = (res(i) + res(i-1))/2.
         else
            SMEAN = res(i)
         endif
         SMOOTHRES(i) = SMEAN
      enddo
C
C------------------------------------ Counting number of zero crossings
C
      Call Vzero(zero_cross,k_hit)
      nzero_cross = 0
      do i=1,(k_hit-1)
         sign = smoothres(i)*smoothres(i+1)
         if(sign.lt.0) then
            nzero_cross = nzero_cross + 1
            zero_cross(i) = 1
         endif
      enddo 
C
      kink_fnd = -500
      fraczero = float(nzero_cross)/float(k_hit)
      If(fraczero.gt.cut_cross) go to 999
C
C----------------------------------------- Maximum spot size 
C
      Call VZERO(SPOT_SIZE,K_HIT)
      CONS = .FALSE.
      nsp = 0
      maxspotsize = 0
      last_cross = -99
C     
      Do i = 1,k_hit-1
         If(zero_cross(i).gt.0.) then
            cons = (i - last_cross).le.2
            if(cons) then
               spot_size(nsp) = spot_size(nsp) + 1
               if(spot_size(nsp).gt.maxspotsize) then
                  maxspotsize = spot_size(nsp)
               endif
               last_cross = i
            else
               nsp = nsp + 1
               spot_size(nsp) =  spot_size(nsp) + 1
               if(spot_size(nsp).gt.maxspotsize) then
                  maxspotsize = spot_size(nsp)
               endif
               last_cross = i
               Spot_ini(nsp) = float(i)
            endif
         endif
      Enddo
C
      Avspotsize = float(maxspotsize)/float(k_hit)
C
      kink_fnd = -600
      If(Avspotsize.gt.cut_spsize) go to 999
C
C--------------------------------------------Average gap
      Av_gap = 0.
      If (nsp.lt.2) then
         go to 999
      endif
C     
      Av_gap = spot_ini(1) - 1.
      do i = 2,nsp
         Av_gap = Av_gap + 
     &           (spot_ini(i)-spot_ini(i-1)) - spot_size(i-1)
      enddo
      Av_gap = Av_gap + (k_hit - spot_ini(nsp) -
     &                spot_size(nsp))
C 
      Av_gap = Av_gap/float(nsp+1)
C
      kink_fnd = -700
      If(Av_gap.lt.cut_gap) go to 999
C
C=============================================================YES, BUT WHERE IS IT ???
C
      n_k = 0
C---------------------------Study of the derivative
C
      zero = sqrt(2.)*rsigma/cut_zero
      do i=1,(k_hit-1)
         diffres = (smoothres(i+1)-smoothres(i))
         if(diffres.lt.-zero) then
            sign_sres(i) = -1
         else if(diffres.lt.zero) then
            sign_sres(i) = 0
         else
            sign_sres(i) = 1
         endif
      enddo 
C
C
      do i=1,(k_hit-1)
         sign = (sign_sres(i+1)*sign_sres(i))
         if(sign.lt.0.) then
            n_k = n_k + 1
            kpos(n_k) = i+1
         endif
      enddo
C
C      
C--------------------------------At most one kink ?
      IF(n_k.eq.0) THEN
         kink_fnd = -800
         go to 999
      ELSEIF(n_k.eq.1) THEN
         if(kpos(1).lt.5) then
            kink_fnd = -830
            go to 999
         elseif(kpos(1).gt.(k_hit-5)) then
            kink_fnd = -860
            go to 999
         else
            kink_fnd = kpos(n_k)
            go to 777
         endif
      ENDIF

C--------------------------We have more than one kink cand.
C
C-------------Filter out external kinks
C
      do k = 1, n_k
         if(kpos(k).lt.5) then
            kpos(k) = -kpos(k)
            go to 666
         elseif(kpos(k)
     &           .gt.(k_hit-5)) then
            kpos(k) = -kpos(k)
            go to 666
         endif
 666     continue
      enddo
C     
      nn = 0      
      do k = 1, n_k
         if(kpos(k).gt.0) then
            nn = nn + 1
            cand(nn) = k
         endif
      enddo
C     
      if(nn.eq.0) then
         kink_fnd = -900
         go to 999
      elseif(nn.eq.1) then
         kink_fnd = kpos(cand(nn))
         go to 777
      endif
C
C------------Study sharpness of local maximum or minimum
C
C
      maxres = -10000.
      DO i = 1,nn
         KKK = kpos(cand(i))
         if(KKK.le.0) go to  111
         thisres  = res(kkk)
         pvres1 = res(kkk - 1)
         pvres2 = res(kkk - 2)
         nxres1 = res(kkk + 1)
         nxres2 = res(kkk + 2)
         presm1 = (pvres1+pvres2)/2.
         nresm1 = (nxres1+nxres2)/2.
         diff1  = ((presm1)-(thisres))
         diff2  = ((nresm1)-(thisres))
         log1   = (abs(diff1).ge.(sharp*rsigma))
         log2   = (abs(diff2).ge.(sharp*rsigma))
         if(log1.or.log2) then 
            if (abs(res(KKK)).ge.maxres) then
               maxres = abs(res(KKK))
               kink_fnd = KKK
            endif
         endif
 111     continue
      ENDDO
C
C-------------If everything else fails, find out the absolute 
C             maximum (minimum) of residuals  
C    
      IF(MAXRES.lt.0.) then
         kink_fnd = lvmaxa(res(kkk),k_hit)
      endif
C
C==============================================================WE FOUND IT ! IT`S KINK_FND
C
 777  continue
C

      STUMP1 = k_hit - kink_fnd
      STUMP2 = kink_fnd
      MINSTUMP = MIN(STUMP1,STUMP2)
C
C
      if (MINSTUMP.lt.6) then
         KINK_FLAG = 0
      else
         KINK_FLAG = -1
      endif
C
      IF(KINK_FLAG.ge.0) go to 999
C
      KINKPOS = KINK_FND
C
C   ==============================================================
C     Before hit addition, hit rejection, and so on, 
C     store in a vector the information to be put
C     in the new dprs banks     
C
C
C
      NPOS_1 = 0
      NNEG_1 = 0
      NPOS_2 = 0
      NNEG_2 = 0
      N = NDF1
      DO WHILE(N.GT.0)
         IF(N.LT.KINKPOS) THEN
            STEPS(N) = DFS(N)
            IF(TIDST(LDFL(N)).GT.0.) THEN
               NPOS_1 = NPOS_1 + 1
            ELSE
               NNEG_1 = NNEG_1 + 1
            ENDIF
         ELSE
            STEPS(N)  = DFS(N)
            IF(TIDST(LDFL(N)).GT.0.) THEN
               NPOS_2 = NPOS_2 + 1
            ELSE
               NNEG_2 = NNEG_2 + 1
            ENDIF
         ENDIF                  
         N=NDF(N)              
      ENDDO
C
      NHITS1 = NPOS_1 + NNEG_1
      NHITS2 = NPOS_2 + NNEG_2
C
C-----------------------------Last step of first stump must be zero!
      STEPS(KINKPOS-1) = 0.
C
C                    
      PAR1(1) = DFX(NDF1)
      PAR1(2) = DFY(NDF1)
      PAR1(3) = DFZ(NDF1)
      PAR1(4) = DFX(KINKPOS-1) ! This is right only if this routine      
      PAR1(5) = DFY(KINKPOS-1) ! is called BEFORE any addition/rejection 
      PAR1(6) = DFZ(KINKPOS-1) ! of hits, so NDF is still SEQUENCIAL     
      PAR1(7) = DFKURV
      PAR1(8) = DFPHI
      PAR1(9) = DFCTGT
C
C
      PAR2(1) = DFX(KINKPOS) ! This is right only if this routine      
      PAR2(2) = DFY(KINKPOS) ! is called BEFORE any addition/rejection 
      PAR2(3) = DFZ(KINKPOS) ! of hits, so NDF is still SEQUENCIAL     
      PAR2(4) = DFX(NDFL)
      PAR2(5) = DFY(NDFL)
      PAR2(6) = DFZ(NDFL)
      PAR2(7) = DFKURV
      PAR2(8) = ATAN2(DFPY(KINKPOS), DFPX(KINKPOS))
      PAR2(9) = DFCTGT
C

C
 999  CONTINUE
C
      IF(KINK_FND.lt.0) then
         Call HFILL(71,-FLOAT(KINK_FND),0.,1.)
      ELSE
         CALL HFILL(72,FLOAT(KINK_FND),0.,1.)
      ENDIF
C

C
C
      RETURN
      END
[KLOE] [Offline Doc] [TRK Files]
Generated with Light on Thu Apr 8 13:00:16 MET DST 1999 .
Mail comments and suggestions.