////////////////////////////////////////////////////////////////////////
// $Id: AlgFitTrackSR.h,v 1.21 2007/11/11 08:44:45 rhatcher Exp $
//
// AlgFitTrackSR.h
//
// AlgFitTrackSR is a concrete FitTrackSR Algorithm class.
//
// Author:  R. Lee 2001.03.30
// Revised: B. Rebel 2003.06.27
//
////////////////////////////////////////////////////////////////////////

#ifndef ALGFITTRACKSR_H
#define ALGFITTRACKSR_H

#include<map>
#include "Algorithm/AlgBase.h"
#include "RecoBase/AlgReco.h"
#include "RecoBase/AlgTrack.h"
#include "Validity/VldContext.h"

class TrackClusterSRItr;
class TrackClusterSR;
class CandFitTrackSRHandle;
class CandStripHandleItr;
class KalmanPlaneSR;
class TObjArray;
class UgliGeomHandle;

class AlgFitTrackSR : public AlgBase, public AlgReco, public AlgTrack
{

public:
   AlgFitTrackSR();
   virtual ~AlgFitTrackSR();
   virtual void RunAlg(AlgConfig &ac, CandHandle &ch, CandContext &cx);
   virtual void Trace(const char *c) const;

private:

   VldContext fVldContext; // context of the rec set currently being processed
   Detector::Detector_t fDetector;
   Int_t pRev,pRev2,pFor;
   Int_t fParmMaxIterate;
   Int_t fParmMaxIterate2;
   Double_t fParmQPDiff;
   Double_t fParmMinPlanePE;
   Int_t fParmLastPlane;
   Int_t fParmIsCosmic;
   Double_t fParmMaxLocalChi2;
   Double_t fParmMaxLocalPreChi2;
   Double_t fParmMaxAngleCovariance;
   Double_t fParmMaxImpactParameter;
   Int_t fParmNSkipActive;
   Int_t fParmNSkipView;
   
   Double_t fParmPassReducedChi2;
   Double_t fParmPassPlaneAsymmetry;
   Int_t fParmPassMinPlaneAsymmetry;
   
   Double_t fParmMinClusterCharge;
   Int_t fParmMaxClusterNStrip;

   Double_t fParmDeltaChi2;
   Double_t fParmDeltaCovariance;
   Double_t fParmMisalignmentError; //misalignment in strip tpos

  Double_t fParmDState[5]; //!
  Double_t fParmdedx; //!
  Double_t fParmPlnRadLen; //!
  Int_t    fParmQPRangeCheck; //!
  Double_t fParmMaxQP; //!
  Double_t fParmMaxQPFrac; //!
  Int_t    fSwimmer; //!
  Double_t fParmMaxAngle; //!

  Double_t fParmTPosError2;          
  Double_t fParmInitialPositionError2; 
  Double_t fParmInitialSlopeError2;    
  Double_t fParmInitialQPError2;     
  Double_t fParmCovarianceScale;     
    
// fCov stores the most recent filtered covariance matrix
  Double_t fCov[5][5]; 

  Int_t Predict(KalmanPlaneSR *prevkp, KalmanPlaneSR *currentkp, Int_t idir);

 Int_t Filter(KalmanPlaneSR *currentkp, Int_t idir);
 
 Int_t FitFrom(KalmanPlaneSR *prevkp, KalmanPlaneSR *currentkp, Int_t idir, Int_t iterate);
 
 Int_t CalculatePropagator(KalmanPlaneSR *prevkp, KalmanPlaneSR *currentkp, Int_t idir);
  void CalculateNoise(KalmanPlaneSR *prevkp, KalmanPlaneSR *currentkp, Int_t idir, 
		      Int_t befaft=0);
  void CalculatePreCovariance(KalmanPlaneSR *prevkp, KalmanPlaneSR *currentkp, Int_t idir);
  Int_t CalculatePreState(KalmanPlaneSR *prevkp, KalmanPlaneSR *currentkp, Int_t idir);
  void CalculatePreChi2(KalmanPlaneSR *currentkp, Int_t idir, Double_t = 0.0119);
  void CalculateGain(KalmanPlaneSR *currentkp, Int_t idir, Double_t = 0.0119);
  void CalculateFilState(KalmanPlaneSR *currentkp, Int_t idir);
  void CalculateFilCovariance(KalmanPlaneSR *currentkp, Int_t idir);
  void CalculateFilChi2(KalmanPlaneSR *currentkp, Int_t idir, Double_t = 0.0119);

  Bool_t Swim(Double_t *swimstate, Double_t *state,
	      Double_t zPos, Double_t finalZ, Int_t idir,
              const VldContext*);


  void InitKalmanFitParameters(AlgConfig &ac);

  void InitializeFit(CandFitTrackSRHandle & cfh,Int_t, Int_t);

  void MakeSliceClusterList(TObjArray *trackClusterList, 
			    const TObjArray *tclist,
			    CandStripHandleItr &stripItr, 
			    CandFitTrackSRHandle &cfh);

   void MakeTrackClusterList(TObjArray *trackClusterList, CandStripHandleItr &stripItr,
			     CandFitTrackSRHandle &cfh, Int_t direction);
   void SetTrackParameters(const CandTrackHandle *track0, CandFitTrackSRHandle &cfh,
			   Int_t direction);
   Int_t FindNumSkippedPlanes(Int_t currentPlane, Int_t prevPlane,
			      KalmanPlaneSR *oldkp, 
			      Int_t direction);
   Int_t FindTimingDirection(TrackClusterSRItr  &clusterItr);
   Bool_t MarkTrackClusters(const CandTrackHandle *track0, 
			    TObjArray  &planeClusterList, 
			    CandStripHandleItr &stripItr, CandFitTrackSRHandle &cfh, 
			    Int_t &begPlane, Int_t &endPlane);
   void SetTrackEndParameters(Int_t begPlane, Int_t endPlane, 
			      CandFitTrackSRHandle &cfh,
			      const CandTrackHandle *track0);
   void ResetTrackClusterList(TObjArray &planeClusterList);
   void ResetTrackClusterList(TObjArray &planeClusterList, 
			      CandFitTrackSRHandle &cfh);
   Int_t DoKalmanFit(TObjArray  &planeClusterList, CandFitTrackSRHandle &cfh,
		     Int_t &istatus, Int_t direction, Int_t dosearch);

   Int_t ReverseFit(TObjArray  &planeClusterList,CandFitTrackSRHandle &cfh, Int_t,Bool_t = kFALSE);

   Int_t AddClustersToFit(TObjArray &planeClusterList, CandFitTrackSRHandle &cfh,
			  Int_t iterate, Int_t &nu, Int_t &nv, Int_t direction);
   Int_t RemoveBadPointsFromFit(CandFitTrackSRHandle &cfh, 
				TObjArray &planeClusterList,
				std::map<Int_t,Int_t>& uFitPlanes,
				std::map<Int_t,Int_t>& vFitPlanes, Int_t &nfitu, 
				Int_t &nfitv, Int_t direction);
   Int_t FindDownstreamPlanes(TObjArray &planeClusterList, 
			      CandFitTrackSRHandle &cfh, 
			      Int_t direction);
   Int_t FindUpstreamPlanes(TObjArray &planeClusterList, CandFitTrackSRHandle &cfh,
			    TObjArray *newkplist, Int_t direction);
   Int_t FindNumSkippedPlanesInView(std::map<Int_t,Int_t>& fitPlanes,
				    std::map<Int_t,Int_t>::iterator& fitIter,
				    Int_t currentPlane, Int_t prevPlane,
				    Int_t lastPlane, Int_t direction);
   Int_t AddForwardBestKPToFit(KalmanPlaneSR *bestkp, 
			       CandFitTrackSRHandle &cfh, 	
			       Int_t &nswimfail);

   Int_t AddToFit(CandFitTrackSRHandle & cfh, TrackClusterSR *, Int_t);

   Int_t AddToFit(CandFitTrackSRHandle & cfh, KalmanPlaneSR *, Int_t,Bool_t);

   Int_t AddReverseBestKPToFit(KalmanPlaneSR *bestkp, KalmanPlaneSR *oldkp,
			       CandFitTrackSRHandle &cfh, TObjArray *newkplist,
			       Int_t &nswimfail, Int_t direction);
   void SetPlaneParameters(CandFitTrackSRHandle &cfh, const KalmanPlaneSR *kpu0, 
			   const KalmanPlaneSR *kpu1, const KalmanPlaneSR *kpv0,
			   const KalmanPlaneSR *kpv1);
   void MakeDaughterStripList(CandFitTrackSRHandle &cfh);
   void SwimVertexAndEndPoints(CandFitTrackSRHandle &cfh, KalmanPlaneSR *kp0,
			       KalmanPlaneSR *kp1, const KalmanPlaneSR *kpu0,
			       const KalmanPlaneSR *kpu1, const KalmanPlaneSR *kpv0,
			       const KalmanPlaneSR *kpv1, Double_t *planepe,
			       Int_t plane0, Int_t plane1, Double_t &vtxqp, 
			       Int_t direction);
   Int_t IterateKalmanFit(TObjArray &planeClusterList, CandFitTrackSRHandle &cfh,
			  Int_t &nu, Int_t &nv, Int_t direction, Int_t dosearch);
   

   Int_t FindTimingDirection(CandFitTrackSRHandle &cfh, 
			     Double_t *fitparm,
			     Double_t &timefitchi2);
   
ClassDef(AlgFitTrackSR,8) // FitTrackSR Algorithm Class

};

#endif // ALGFITTRACKSR_H
