#ifndef HKalIFilt_h
#define HKalIFilt_h
#include "TRotation.h"
#include "TMatrixD.h"
class     TVector3;
#include "TVectorD.h"
class HCategory;
class HMdcTrackGField;
#include "hkaldef.h"
#include "hkalrungekutta.h"
#include "hkaltracksite.h"
class HKalIFilt : public TObject {
private:
    Bool_t   bDoDEDX;        
    Bool_t   bDoMS;          
    Bool_t   bDoSmooth;      
    Bool_t   bPrintWarn;     
    Bool_t   bPrintErr;      
    Bool_t   bTrackAccepted; 
    Double_t betaInput;      
    Double_t chi2;           
    Bool_t   direction;      
    Int_t    filtType;       
    Int_t    hitType;        
    TVectorD iniStateVec;    
    Int_t    nCondErrs;      
    Int_t    nCovSymErrs;    
    Int_t    nCovPosDefErrs; 
    Int_t    nKalRuns;       
    Int_t    nHitsInTrack;   
    Int_t    nMaxSites;      
    Int_t    pid;            
    Int_t    rotCoords;      
    Int_t    nSites;         
    Double_t trackLength;    
    Double_t trackLengthAtLastMdc; 
    Int_t    trackNum;       
    HKalTrackSite  **sites;           
    TVector3         posVertex;       
    TVectorD         svVertex;        
    TVector3         posMeta;         
    TVectorD         svMeta;          
    HKalRungeKutta   trackPropagator; 
    TRotation       *pRotMat;         
    TVector3        *pTransVec;       
    Bool_t     bFillPointArrays; 
    TObjArray  pointsTrack;      
    TObjArray  fieldTrack;       
protected:
    virtual Bool_t calcProjector      (Int_t iSite) const = 0;
    virtual Bool_t checkSitePreFilter (Int_t iSite) const;
    virtual void   filterConventional (Int_t iSite);
    virtual void   filterJoseph       (Int_t iSite);
    virtual void   filterSequential   (Int_t iSite);
    virtual void   filterSwerling     (Int_t iSite);
    virtual void   filterUD           (Int_t iSite);
    virtual void   newTrack           (const TObjArray &hits, const TVectorD &iniSv,
				       const TMatrixD &iniCovMat, Int_t pid);
    virtual void   propagateCovUD     (Int_t iFromSite, Int_t iToSite);
    virtual void   propagateCovConv   (Int_t iFromSite, Int_t iToSite);
    virtual Bool_t propagateTrack     (Int_t iFromSite, Int_t iToSite);
    virtual void   updateChi2Filter   (Int_t iSite);
    virtual Kalman::coordSys    getFilterInCoordSys() const { return Kalman::kSecCoord; }
    virtual TRotation*          getRotMat()           const { return pRotMat; }
    virtual void   setChi2            (Double_t c)    { chi2 = c; }
    virtual void   setNSites          (Int_t n)       { nSites = n; }
    virtual void   setNHitsInTrack    (Int_t n)       { nHitsInTrack = n; }
    virtual void   setTrackChi2       (Double_t c)    { chi2 = c; }
    virtual void   setTrackLength     (Double_t l)    { trackLength = l; }
    virtual void   setTrackLengthAtLastMdc (Double_t l)    { trackLengthAtLastMdc = l; }
public:
    HKalIFilt(Int_t nHits, Int_t measDim, Int_t stateDim, HMdcTrackGField *fMap, Double_t fpol);
    virtual ~HKalIFilt();
    virtual Bool_t calcMeasVecFromState      (TVectorD &projMeasVec, HKalTrackSite const* const site,
                                              Kalman::kalFilterTypes stateType, Kalman::coordSys sys) const;
    virtual Bool_t checkCovMat               (const TMatrixD &fCov) const;
    virtual Bool_t excludeSite               (Int_t iSite);
    virtual Bool_t filter                    (Int_t iSite);
    virtual Bool_t fitTrack                  (const TObjArray &hits, const TVectorD &iniStateVec,
					      const TMatrixD &iniCovMat, Int_t pId);
    virtual Bool_t propagate                 (Int_t iFromSite, Int_t iToSite);
    virtual Bool_t propagateToPlane          (TVectorD& svTo, const TVectorD &svFrom,
					      const HKalMdcMeasLayer &measLayFrom, const HKalMdcMeasLayer &measLayTo,
					      Int_t pid, Bool_t dir);
    virtual Bool_t runFilter                 (Int_t fromSite, Int_t toSite);
    virtual Bool_t smooth                    ();
    virtual void   sortHits                  ();
    virtual Bool_t traceToMeta               (const TVector3& metaHit, const TVector3& metaNormVec);
    virtual Bool_t traceToVertex             ();
    virtual void   transformFromSectorToTrack();
    virtual void   transformFromTrackToSector();
    virtual void   updateSites               (const TObjArray &hits);
    virtual Double_t            getBetaInput    () const           { return betaInput; }
    virtual Double_t            getChi2         () const           { return chi2; }
    virtual void                getCovErrs      (Int_t &nSymErrs, Int_t &nPosDefErrs) const { nSymErrs = nCovSymErrs; nPosDefErrs = nCovPosDefErrs; }
    virtual Double_t            getDafChi2Cut   () const           { return -1.; }
    virtual const Double_t*     getDafT         () const           { return NULL; }
    virtual Bool_t              getDirection    () const           { return direction; }
    virtual Bool_t              getDoDaf        () const           { return kFALSE; }
    virtual Bool_t              getDoEnerLoss   () const           { return bDoDEDX; }
    virtual Bool_t              getDoMultScat   () const           { return bDoMS; }
    virtual Bool_t              getDoSmooth     () const           { return bDoSmooth; }
    virtual Double_t            getFieldIntegral() const           { return trackPropagator.calcFieldIntegral().Mag(); }
    virtual Int_t               getFilterMethod () const           { return filtType; }
    virtual TVectorD  const&    getIniStateVec  () const           { return iniStateVec; }
    virtual TObjArray const&    getFieldTrack   () const           { return fieldTrack; }
    virtual TMatrixD  const&    getHitErrMat    (HKalTrackSite* const site) const;
    virtual Int_t               getHitType      () const           { return hitType; }
    virtual TVectorD  const&    getHitVec       (HKalTrackSite* const site) const;
    virtual Bool_t              getLastTrackAccepted() const       { return bTrackAccepted; }
    virtual Int_t               getMeasDim      () const           { return getSite(0)->getMeasDim(); }
    virtual void                getMetaPos      (Double_t &x, Double_t &y, Double_t &z) const;
    virtual Int_t               getNdafs        () const           { return 0; }
    virtual Double_t            getNdf          () const;
    virtual Int_t               getNhits        () const           { return nHitsInTrack; }
    virtual Int_t               getNiter        () const           { return nKalRuns; }
    virtual Int_t               getNmaxSites    () const           { return nMaxSites; }
    virtual Int_t               getNsites       () const           { return nSites; }
    virtual Int_t               getPid          () const           { return pid; }
    virtual TObjArray const&    getPointsTrack  () const           { return pointsTrack; }
    virtual const HKalRungeKutta* getTrackPropagator()  const      { return &trackPropagator; }
    virtual inline HKalTrackSite* getSite       (UInt_t site) const {
#if kalDebug > 0
        if(site < (UInt_t)nMaxSites) {
            return sites[site];
        } else {
            Warning("getSite()", Form("Index %i out of range.", site));
            return NULL;
        }
#else
        return sites[site];
#endif
    }
    virtual Bool_t              getPrintErr     () const           { return bPrintErr; }
    virtual Bool_t              getPrintWarn    () const           { return bPrintWarn; }
    virtual Int_t               getRotation     () const           { return rotCoords; }
    virtual Int_t               getStateDim     (Kalman::coordSys coord=kSecCoord) const { return getSite(0)->getStateDim(coord); }
    virtual Double_t            getTrackLength  () const           { return trackLength; }
    virtual Int_t               getTrackNum     () const           { return trackNum; }
    virtual void                getVertexPos    (Double_t &x, Double_t &y, Double_t &z) const;
    virtual void setBetaInput       (Double_t b)                              { betaInput = b; }
    virtual void setConstField      (Bool_t constField)                       { trackPropagator.setUseConstField(constField); }
    virtual void setDafPars         (Double_t chi2cut, const Double_t *T, Int_t n) { ; }
    virtual void setDirection       (Bool_t dir)                              { direction = dir; trackPropagator.setDirection(dir); }
    virtual void setDoEnerLoss      (Bool_t dedx)                             { bDoDEDX = dedx; trackPropagator.setDoEnerLoss(dedx); }
    virtual void setDoMultScat      (Bool_t ms)                               { bDoMS = ms; trackPropagator.setDoMultScat(ms); }
    virtual void setFillPointsArrays(Bool_t fill)                             { bFillPointArrays = fill; trackPropagator.setFillPointsArrays(fill); }
    virtual void setFieldMap        (HMdcTrackGField *fMap, Double_t fpol)    { trackPropagator.setFieldMap(fMap, fpol); }
    virtual void setFieldVector     (const TVector3 &B)                       { trackPropagator.setFieldVector(B); }
    virtual void setFilterMethod    (Kalman::filtMethod type)                 { filtType = type; }
    virtual void setHitType         (Kalman::kalHitTypes hType)               { hitType = hType; }
    virtual void setNumIterations   (Int_t kalRuns)                           { nKalRuns = kalRuns; }
    virtual void setPrintWarnings   (Bool_t print);
    virtual void setPrintErrors     (Bool_t print);
    virtual void setRotationAngles  (Double_t rotXAngle, Double_t rotYAngle);
    virtual void setRotation        (Kalman::kalRotateOptions rotate);
    virtual void setRungeKuttaParams(Float_t initialStpSize, Float_t stpSizeDec,
				     Float_t stpSizeInc, Float_t maxStpSize,
				     Float_t minStpSize, Float_t minPrec,
				     Float_t maxPrec, Int_t maxNumStps,
				     Int_t maxNumStpsPCA, Float_t maxDst,
				     Double_t minLngthCalcQ) { trackPropagator.setRungeKuttaParams(initialStpSize, stpSizeDec, stpSizeInc, maxStpSize, minStpSize, minPrec, maxPrec, maxNumStps, maxNumStpsPCA, maxDst, minLngthCalcQ); }
    virtual void setSmoothing       (Bool_t smooth)                           { bDoSmooth = smooth; }
    ClassDef(HKalIFilt,0)
};
#endif // HKalIFilt_h