module Track_mod
        ! Uses
    use Precision_mod
        ! Types
    public type fgresult_type
    public type dHelix_type
    public type helixfit_type
        ! Variables
    integer, public, PARAMETER :: MaxTracks = 150
    integer, public, PARAMETER :: MaxPCTrackHits = 100
    integer, public, PARAMETER :: MaxDCTrackHits = 500
    integer, public, PARAMETER :: MaxHelixKinks = 20
    integer, public :: nFGResult
    type (fgresult_type), public, TARGET, dimension (MaxTracks) :: FGResult
    real (kind=r8), public :: fgpar1
    real (kind=r8), public :: fgpar2
    real (kind=r8), public :: fgpar3
    integer (kind=I4), public, PARAMETER :: FGNoFail = 0
    integer (kind=I4), public, PARAMETER :: FGNoDecay = 1
    integer (kind=I4), public, PARAMETER :: FGFailMultiple = 2
    integer (kind=I4), public, PARAMETER :: FGFailMissedPlanes = 3
    integer (kind=I4), public, PARAMETER :: FGFailOmegaMisMatch = 4
    integer, public, PARAMETER :: kSuccess = 0
    integer, public, PARAMETER :: kFailUnknown = 1
    integer, public, PARAMETER :: kFailTooFewHits = 2
    integer, public, PARAMETER :: kFailRes0 = 3
    integer, public, PARAMETER :: kFailRes1 = 4
    integer, public, PARAMETER :: kFailGradAdd = 5
    integer, public, PARAMETER :: kFailStepInvert = 6
    integer, public, PARAMETER :: kFailGradNumRes = 7
    integer, public, PARAMETER :: kFailGsetupRes0 = 8
    integer, public, PARAMETER :: kFailGsetupAdd = 9
    integer, public, PARAMETER :: kFailMaxIter = 10
    integer, public, PARAMETER :: kFailBadInput = 11
    integer, public, PARAMETER :: kFailFitGrad = 12
    integer, public, PARAMETER :: kFailInitConf = 13
    integer, public, PARAMETER :: kFailLostAllHits = 14
    integer, public, PARAMETER :: kFailLostAllGrad = 15
    integer, public, PARAMETER :: kFailFiducial = 16
    integer, public, PARAMETER :: kFailUVplanes = 17
    integer, public, PARAMETER :: kFailFirstHit = 18
    integer, public, PARAMETER :: kFailBadStep = 19
    integer, public, PARAMETER :: kFailZeroGrad = 21
    integer, public, PARAMETER :: kFailGradSTR = 22
    integer, public, PARAMETER :: kFailTrackswim = 23
    integer, public, PARAMETER :: kFailBadMagnet = 24
    integer, public, PARAMETER :: kFailBadRadius = 25
    integer, public, PARAMETER :: kFailBadKink = 26
    integer, public, PARAMETER :: kFailBadChiSqr = 27
    integer, public, PARAMETER :: kFailLastUsed = 28
    integer, public, PARAMETER :: kFGerror = 35
    integer, public, PARAMETER :: kFailMultFailTrks = 36
    integer, public, PARAMETER :: kFailMultParticles = 37
    integer, public, PARAMETER :: kFailDecayMove = 38
    integer, public, PARAMETER :: kFailNoFit = 39
    type (helixfit_type), public, TARGET, dimension (MaxTracks) :: fHelixFits
    integer, public :: fNumHelixFits
        ! Subroutines and functions
    public subroutine ConvertParToVPQ (par, v, p, q)
    public subroutine ConvertFGtoPcosth (fg, p, costh)
    public subroutine ConvertFGZtoVPQ (fg, z, v, p, q)
    public function ConvertVPQtoFG (fg, V, P, q) result (iStat)
    private subroutine TrackFGtoZ (fg, z)
    public subroutine PrintHelixFit (iunit, fit)
    public subroutine PrintFGresult (iunit, fg)
end module Track_mod
public type fgresult_type
    character :: FGVersion
            Version of FG used to produce track
    integer :: nPCHits
                                          !!'D'-DenseOmegaPhiNot
number of PC hits
    integer, dimension (MaxPCTrackHits) :: PCHit
            indices into PCTDC
    integer :: nDCHits
            number of DC hits
    integer, dimension (MaxDCTrackHits) :: DCHit
            indices into DCTDC
    integer :: iwindow
            time window
    real (kind=R8) :: Area
            average area of clusters
    real (kind=R8) :: Size
            average "invariant size" of clusters
    integer :: ifgerror
            fg error code
    integer :: istream
            -1 upstream, +1 downstream, 0 both
    real (kind=R8) :: t0
            track time
    integer :: uvNumHits
            number of hits in u-v and phase fits
    integer :: phaseNumHits
            number of hits in u-v and phase fits
    real (kind=R8) :: uvChiSqr
            chi-sqr for u-v and phase fits
    real (kind=R8) :: phaseChiSqr
            chi-sqr for u-v and phase fits
    real (kind=R8) :: uvConfLevel
            confidence levels for u-v and phase fits
    real (kind=R8) :: phaseConfLevel
            confidence levels for u-v and phase fits
    real (kind=R8), dimension (8) :: aPar
            helix parameters as defined below:
    real (kind=R8) :: zNot
            u = a1*cos[a2*z + a3] + a4
v = a1*sin[a2*z + a3] + a5
where a1 means aPar(1), a2 is aPar(2), etc.
aPar(6) is t0
aPar(7) is the U-V Chi-Square
aPar(8) is the Phase Chi-Square
end type fgresult_type
public type dHelix_type
    real (kind=R8) :: uc
    real (kind=R8) :: vc
    real (kind=R8) :: PT
    real (kind=R8) :: PL
    real (kind=R8) :: w
    real (kind=R8) :: phi
end type dHelix_type
public type helixfit_type
    integer :: ierror
             error code
    real (kind=R8), dimension (3) :: V
             track starting position, UVZ coordinates, cm
    real (kind=R8), dimension (3) :: P
             track starting momentum, UVZ coordinates, MeV/c
    integer :: Q
             charge
    real (kind=R8) :: mass
             particle mass, MeV/c^2
    real (kind=R8) :: Tstart
             track start time (muon decay time), ns
    integer :: iwindow
             time window
    integer :: InputHits
             first guess number of hits
    real (kind=R8), dimension (3) :: InputV
             first guess track starting position (UVZ)
    real (kind=R8), dimension (3) :: InputP
             first guess track starting momentum (UVZ)
    integer :: NumHits
             Number of hits used in fit
    integer :: NumDOF
             Degrees of freedom
    real (kind=R8) :: ChiSqr
             Chi Squared
    real (kind=R8) :: ConfLevel
             confidence level
    real (kind=R8) :: ChebyshevNorm
             Wire-center fit Chebyshev norm: biggest residual
    integer :: numIterations
             number of fit iterations
    real (kind=R8) :: elossHe
             energy loss in He volume, MeV/c per cm
    real (kind=R8) :: elossDC
             energy loss in DC gas volume, MeV/c per cm
    real (kind=R8) :: elossFoil
             energy loss in DC foils, MeV/c per foil
    integer, dimension (MaxDCTrackHits) :: ifghit
             these arrays contain NumHits entries.
 index into FGresult%DChit() array
    integer, dimension (MaxDCTrackHits) :: idchit
             index into DCtdcs() array
    integer, dimension (MaxDCTrackHits) :: iplane
             plane number
    integer, dimension (MaxDCTrackHits) :: iwire
             wire number
    integer, dimension (MaxDCTrackHits) :: iambig
             left-right ambiguity (-1, 0, 1)
    integer, dimension (MaxDCTrackHits) :: imcambig
             true ambiguity from geant (-1, 0, 1)
    real (kind=R8), dimension (MaxDCTrackHits) :: dtrk
             fit drift distance
    real (kind=R8), dimension (MaxDCTrackHits) :: ttrk
             fit drift time
    real (kind=R8), dimension (MaxDCTrackHits) :: dhit
             measured drift distance
    real (kind=R8), dimension (MaxDCTrackHits) :: thit
             measured drift time (incl tof correction)
    real (kind=R8), dimension (MaxDCTrackHits,3) :: wirepos
             wire position at each hit (u-v-z)
    real (kind=R8), dimension (MaxDCTrackHits,3) :: trkpos
             fit track position at each hit (u-v-z)
    real (kind=R8), dimension (MaxDCTrackHits,3) :: trkmom
             fit track momentum at each hit (u-v-z)
    real (kind=R8), dimension (MaxDCTrackHits,3) :: hitpos
             fit hit position at each hit (u-v-z)
    real (kind=R8), dimension (MaxDCTrackHits) :: weights
             weight of this hit (0 if hit not used in fits)
    integer :: NumKinks
             Kink data
 Number of kinks
    real (kind=R8), dimension (MaxHelixKinks) :: kinkZ
             Z coordinate of kink
    real (kind=R8), dimension (MaxHelixKinks) :: kinkSigma
             kink width, radians
    real (kind=R8), dimension (MaxHelixKinks) :: kinkUangle
             kink in UZ projection, radians
    real (kind=R8), dimension (MaxHelixKinks) :: kinkVangle
             kink in VZ projection, radians
    real (kind=R8), dimension (MaxHelixKinks) :: kinkUcl
             confidence level of UZ kink
    real (kind=R8), dimension (MaxHelixKinks) :: kinkVcl
             confidence level of VZ kink
    logical :: kinkTarget
             Target kink
 true if have a target kink
    real (kind=R8) :: kinkTargetUangle
             kink in UZ projection, radians
    real (kind=R8) :: kinkTargetVangle
             kink in VZ projection, radians
    real (kind=R8) :: kinkTargetEloss
             target energy loss, MeV/c
end type helixfit_type
integer, public, PARAMETER :: MaxTracks = 150
integer, public, PARAMETER :: MaxPCTrackHits = 100
integer, public, PARAMETER :: MaxDCTrackHits = 500
integer, public, PARAMETER :: MaxHelixKinks = 20
integer, public :: nFGResult
type (fgresult_type), public, TARGET, dimension (MaxTracks) :: FGResult
real (kind=r8), public :: fgpar1
real (kind=r8), public :: fgpar2
real (kind=r8), public :: fgpar3
integer (kind=I4), public, PARAMETER :: FGNoFail = 0 FirstGuess Fitter Error Codes
integer (kind=I4), public, PARAMETER :: FGNoDecay = 1
integer (kind=I4), public, PARAMETER :: FGFailMultiple = 2
integer (kind=I4), public, PARAMETER :: FGFailMissedPlanes = 3
integer (kind=I4), public, PARAMETER :: FGFailOmegaMisMatch = 4
integer, public, PARAMETER :: kSuccess = 0 helixfit_type ierror values: no failure
integer, public, PARAMETER :: kFailUnknown = 1 unknown error
integer, public, PARAMETER :: kFailTooFewHits = 2 too few hits to fit a track
integer, public, PARAMETER :: kFailRes0 = 3 cannot make initial residuals
integer, public, PARAMETER :: kFailRes1 = 4 cannot make residuals for new iteration
integer, public, PARAMETER :: kFailGradAdd = 5 cannot update gradient for new iteration
integer, public, PARAMETER :: kFailStepInvert = 6 cannot invert matrix in llsq step
integer, public, PARAMETER :: kFailGradNumRes = 7 wrong number of residuals in gradient
integer, public, PARAMETER :: kFailGsetupRes0 = 8 gradient setup: base residuals
integer, public, PARAMETER :: kFailGsetupAdd = 9 gradient setup: add residuals
integer, public, PARAMETER :: kFailMaxIter = 10 too many fit iterations
integer, public, PARAMETER :: kFailBadInput = 11 bad input parameters
integer, public, PARAMETER :: kFailFitGrad = 12 cannot fit gradient
integer, public, PARAMETER :: kFailInitConf = 13 bad initial conf level
integer, public, PARAMETER :: kFailLostAllHits = 14 lost all hits
integer, public, PARAMETER :: kFailLostAllGrad = 15 lost all gradient points
integer, public, PARAMETER :: kFailFiducial = 16 did not pass fiducial cuts
integer, public, PARAMETER :: kFailUVplanes = 17 too few U and V planes
integer, public, PARAMETER :: kFailFirstHit = 18 cannot track to first hit
integer, public, PARAMETER :: kFailBadStep = 19 bad step while iterating
integer, public, PARAMETER :: kFailZeroGrad = 21 INTEGER, PARAMETER, PUBLIC:: kFailNoFit = 20 !! unused slot (moved to 40). gradient is zero
integer, public, PARAMETER :: kFailGradSTR = 22 gradient "usesSTR" mismatch
integer, public, PARAMETER :: kFailTrackswim = 23 cannot propagate track to plane
integer, public, PARAMETER :: kFailBadMagnet = 24 field map returned an error
integer, public, PARAMETER :: kFailBadRadius = 25 bad radius in ABCFP parametrization
integer, public, PARAMETER :: kFailBadKink = 26 kink is too big while iterating
integer, public, PARAMETER :: kFailBadChiSqr = 27 bad chi squared while iterating
integer, public, PARAMETER :: kFailLastUsed = 28 last used failure code
integer, public, PARAMETER :: kFGerror = 35 When adding new helix fitter error codes, please increment kFailLastUsed. K.O. 25 May 2003. ***************** NOTICE ************************************************* Additions should be cooordinated with update to Subroutine InitTracking in tracking_mod ************************************************************************** Additional error codes that identify the error that results in the failure of this track like error codes should. The difference is that these do not originate with the fitter. However, they apply to tracks recorded in the same structure. The must be labeled so a check of the track ierror code will tell whether the track was successfully fit. FG failure
integer, public, PARAMETER :: kFailMultFailTrks = 36 Error codes for the decay positron fit status. When adding new codes, be careful to avoid overlaps with the helixfit error codes above. Multiple failing tracks in decay window
integer, public, PARAMETER :: kFailMultParticles = 37 Multiple particles in decay window
integer, public, PARAMETER :: kFailDecayMove = 38 Overlap code changed
integer, public, PARAMETER :: kFailNoFit = 39 empty fit structure without valid data
type (helixfit_type), public, TARGET, dimension (MaxTracks) :: fHelixFits
integer, public :: fNumHelixFits
public subroutine ConvertParToVPQ (par, v, p, q)
    real (kind=R4), INTENT(in), dimension (5) :: par
            
 Description: convert the "track parameters" into
              starting point, momentum and charge
 Arguments:
 track parameters
    real (kind=R8), INTENT(out), dimension (3) :: v
             starting point
    real (kind=R8), INTENT(out), dimension (3) :: p
             momentum
    integer, INTENT(out) :: q
             charge
end subroutine ConvertParToVPQ
public subroutine ConvertFGtoPcosth (fg, p, costh)
    type (fgresult_type), INTENT(in) :: fg
             FGResult
    real (kind=R8), INTENT(out) :: p
             Total momentum
    real (kind=R8), INTENT(out) :: costh
             cos(theta)
end subroutine ConvertFGtoPcosth
public subroutine ConvertFGZtoVPQ (fg, z, v, p, q)
    type (FGresult_type), INTENT(in) :: fg
             input first-guess data
    real (kind=R8), INTENT(in) :: z
             z coordinate
    real (kind=R8), INTENT(out), dimension (3) :: v
             track position
    real (kind=R8), INTENT(out), dimension (3) :: p
             track momentum
    integer, INTENT(out) :: q
             track charge
end subroutine ConvertFGZtoVPQ
public function ConvertVPQtoFG (fg, V, P, q) result (iStat)
    type (fgresult_type), INTENT(out) :: fg
             FirstGuess parameterization
    real (kind=R8), DIMENSION(:), INTENT(in) :: V
             Fitter position vector (cm)
    real (kind=R8), DIMENSION(:), INTENT(in) :: P
             Fitter momentum vector (MeV/c)
    integer (kind=I4), INTENT(in) :: q
             charge
    integer (kind=I4) :: iStat
             Status, 0 is successful call
    ! Calls: TrackFGtoZ
end function ConvertVPQtoFG
----------------------------------------------------------------------------
 ConvertVPtoFG converts from HelixFit parameterization, V(3) and P(3), to
 FirstGuess parameterization, aPar(5).
 Firstguess parameterization assumes z of target.  Fixed code to accomodate
 this.  Completely rewritten April 22,2004. (jrm)
----------------------------------------------------------------------------
private subroutine TrackFGtoZ (fg, z)
    type (fgresult_type), INTENT(inout) :: fg
    real (kind=R8) :: z
end subroutine TrackFGtoZ
----------------------------------------------------------------------------
 TrackFGtoZ translates firstguess parameters to parameters at a given z
  April 22, 2004
----------------------------------------------------------------------------
Author: Jim
public subroutine PrintHelixFit (iunit, fit)
    integer, INTENT(in) :: iunit
    type (helixfit_type), INTENT(in) :: fit
end subroutine PrintHelixFit
public subroutine PrintFGresult (iunit, fg)
    integer, INTENT(in) :: iunit
    type (FGresult_type), INTENT(in) :: fg
end subroutine PrintFGresult