// LCDVtopl.h
//
// Feb 14 2001 Toshi Abe  Modify GetSeedVertex...
// Sep 11 2000 M.Iwasaki  Add CalcPTMass and GetSeedVertex functions.
// Aug 15 2000 Toshi Abe  Program creation. 
//                        Original version copied from D.Jackson's ZVTOP3
//
#ifndef LCDVTOPL_H
#define LCDVTOPL_H

#include "TClonesArray.h"
#include "LCDVToplTRK.h"
#include "LCDVToplVRT.h"

extern "C"{
    Int_t LCDNNSeedVertex(Float_t *in, Float_t *out, Int_t init);
    Int_t LCDNNTrackAttach(Float_t *in, Float_t *out, Int_t init);
    Int_t LCDNNHFSelect(Float_t *in, Float_t *out, Int_t init);
}

class LCDVTopl: public TObject {

public:
  //Constructor and Deconstructor
  LCDVTopl();
  LCDVTopl(TObjArray* track_list, Int_t ntrk, Int_t* track_indecies, 
	   const TVector3& ip_position, const TVector3& bfield_vector);
  LCDVTopl(TObjArray* track_list, Int_t ntrk, Int_t* track_indecies, 
	   const TVector3& ip_position, const TVector3& bfield_vector,
	   const TVector3& jet_axis);
  LCDVTopl(TObjArray* track_list, 
	   const TVector3& ip_position, const TVector3& bfield_vector,
	   const TVector3& jet_axis);
  ~LCDVTopl();
  
  void SetUpLCDVTopl(TObjArray* track_list, Int_t ntrk, Int_t* track_indecies, 
		     const TVector3& ip_position, 
		     const TVector3& bfield_vector);
  void SetUpLCDVTopl(TObjArray* track_list, Int_t ntrk, Int_t* track_indecies, 
		     const TVector3& ip_position, 
		     const TVector3& bfield_vector,
		     const TVector3& jet_axis);
  void SetUpLCDVTopl(TObjArray* track_list, 
		     const TVector3& ip_position, 
		     const TVector3& bfield_vector,
		     const TVector3& jet_axis);

  Double_t       GetRipe() { return ripe; } //Get Ripe cut value
  Double_t       GetZipe() { return zipe; } //Get Zipe cut value
  TVector3       GetPja()  { return pja;  } //Get pja      value
  TVector3       GetPtks() { return ptks; } //Get ptrks    value
  Double_t       GetRcut() { return rcut; } //Get rcut cut value
  Double_t       GetXcut() { return xcut; } //Get xcut cut value
  Double_t       GetKang() { return kang; } //Get kang cut value
  Double_t       GetKipw() { return kipw; } //Get kipw cut value
  
  // Get the Cut values for Track attaching.
  Double_t       GetTrdiMax() { return m_TrdiMax; }
  Double_t       GetLodiMin() { return m_LodiMin; }
  Double_t       GetLodrMin() { return m_LodrMin; }
  Double_t       GetLodrMax() { return m_LodrMax; }
  Double_t       GetAntaMax() { return m_AntaMax; }

  // Set the Cut values for Seed Vertex Finding.
  Double_t       GetSeedVrtRMax()        { return m_SeedVrtRMax;        }
  Double_t       GetSeedVrtK0Mass()      { return m_SeedVrtK0Mass;      }
  Double_t       GetSeedVrtLambda0Mass() { return m_SeedVrtLambda0Mass; }
  Double_t       GetSeedVrtSigMin()      { return m_SeedVrtSigMin;      }
  
  // PT correction stuff
  Double_t*      GetPTIP()    { return m_PTIP;    }
  Double_t       GetPTIPXY()  { return m_PTIP[0]; }
  Double_t       GetPTIPZ()   { return m_PTIP[1]; }
  Double_t       GetNVsigma() { return m_NVsigma; }

  Double_t       GetIPProbabirity(TVector3 xvrt);//Get IP probabirity
  //Get Initial vertexposition track and track 
  TVector3       GetInitialVertexT2T(Int_t itrk,Int_t jtrk);
  //Get Initial vertexposition ip and track 
  TVector3       GetInitialVertexIP2T(Int_t jtrk);
  //Get vertex significance
  Double_t       GetVertexSignificance(TVector3 xvrt);
  //Get min(Vr/min(V))
  Double_t       GetMinVrOverMinVs(LCDVToplVRT* vrt1, LCDVToplVRT* vrt2, 
				   Int_t nstp);
  Double_t       GetMinVrOverMinVs(LCDVToplVRT* vrt1, LCDVToplVRT* vrt2);
  //Get Vertex by simple iteration
  TVector3       GetVertexBySimpleIteration(LCDVToplVRT* vrt);
  //Get Vertex Charge
  Double_t       GetVertexCharge();
  
  // Return ID number of Seed Vertex. 
  Int_t          GetSeedVertex(); // = -1 There is no seed vertex.
  Int_t          GetSeedVertexByClassicMethod(); // imethod=1
  Int_t          GetSeedVertexByNNMethod(); // imethod=2
  
  // Vertex mass and momentum...
  Double_t       GetRawMass()  { return m_Rmass;    }
  Double_t       GetPtMass()   { return m_PtMass;   }
  Double_t       GetPtMassErr(){ return m_PtMassEr; }
  Double_t       GetMassTag()  { return m_Masstag;  }
  Double_t       GetMissPt()   { return m_MissPt; }
  TLorentzVector GetP4Vertex() { return m_p4Vertex; }

  
  // Tracks and vertieces...
  Int_t          GetTrackEntries();  //Get # of tracks
  LCDVToplTRK*   GetTrackAt(Int_t i);
  Int_t          GetVertexEntries();
  Int_t          GetVertexEntriesExceptV0();
  LCDVToplVRT*   GetVertexAt(Int_t i);
  Int_t          GetVrtTrackEntries();
  LCDVToplTRK*   GetVrtTrackAt(Int_t i);
  
  // Nsig...
  Int_t          GetNsig(Double_t nsigma, TVector3 axis, TVector3 xfrom, 
			 TMatrixD& exfrom);
  Int_t          GetNsig(Double_t nsigma);
  Int_t          GetNsig(Double_t nsigma, TVector3 axis, TVector3 xfrom, 
			 TMatrixD& exfrom,TObjArray* nsig_list);
  Int_t          GetNsig(Double_t nsigma,TObjArray* nsig_list);
  Int_t          GetNsig(Double_t nsigma, TVector3 axis, TVector3 xfrom, 
			 TMatrixD& exfrom,TObjArray* nsig_list,
			 Double_t rnsigcut, Double_t znsigcut);
  Int_t          GetNsig(Double_t nsigma,TObjArray* nsig_list,
			 Double_t rnsigcut, Double_t znsigcut);

  // Debug level
  Int_t          GetDebugLevel() { return dblv;} //Get Debug Level

  // Get NN...
  Bool_t         GetUseNN()              { return m_UseNN;     }
  Double_t       GetSeedVertexNN()       { return m_SeedVrtNN; }
  Double_t       GetTrackAttachNN()      { return m_TrackAttNN;}
  Double_t       GetHFSelectNN()         { return m_SelectNN; }
  Double_t       GetHFTagNN(); // NN output for HF jet tag
      //if < 0.0, no seed vertex...
  Double_t       GetHFTagNN(Int_t iseed); // NN output for HF jet tag
      //if < 0.0, no seed vertex...

  // Set the cut valuables for topological vertex finding...
  void           SetLCDVToplTRKs(TObjArray*, Int_t, Int_t*);
  void           SetRipe(Double_t a) { ripe=a; } //Unit in cm.
  void           SetZipe(Double_t a) { zipe=a; } //Unit in cm.
  void           SetPja(TVector3 a)  { pja =a; }
  void           SetRcut(Double_t a) { rcut=a; }
  void           SetXcut(Double_t a) { xcut=a; }
  void           SetKang(Double_t a) { kang=a; }
  void           SetKipw(Double_t a) { kipw=a; }
  
  // Set the Cut values for Seed Vertex Finding.
  void           SetSeedVrtRMax(Double_t a)        { m_SeedVrtRMax=a;        }
  void           SetSeedVrtK0Mass(Double_t a)      { m_SeedVrtK0Mass=a;      }
  void           SetSeedVrtLambda0Mass(Double_t a) { m_SeedVrtLambda0Mass=a; }
  void           SetSeedVrtSigMin(Double_t a)      { m_SeedVrtSigMin=a;      }
  void           SetSeedVrtNN(Double_t a)          { m_SeedVrtNN=a;          }
  
  // Set the Cut values for Track attaching.
  void           SetTrdiMax(Double_t a) { m_TrdiMax=a; }
  void           SetLodiMin(Double_t a) { m_LodiMin=a; }
  void           SetLodrMin(Double_t a) { m_LodrMin=a; }
  void           SetLodrMax(Double_t a) { m_LodrMax=a; }
  void           SetAntaMax(Double_t a) { m_AntaMax=a; }

  // PT correction stuff
  void           SetPTIP(Double_t* a)  { m_PTIP[0] = a[0]; m_PTIP[1] = a[1];}
  void           SetPTIPXY(Double_t a) { m_PTIP[0] = a; }
  void           SetPTIPZ(Double_t a)  { m_PTIP[1] = a; }
  void           SetNVsigma(Double_t a){ m_NVsigma = a; }
  
  // Set debug level
  void           SetDebugLevel(Int_t a) { dblv=a; } //Set Debug Level

  // Set NN...
  void           SetUseNN(Bool_t a)                { m_UseNN=a;     }
  void           SetSeedVertexNN(Double_t a)       { m_SeedVrtNN=a; }
  void           SetTrackAttachNN(Double_t a)      { m_TrackAttNN=a;}
  void           SetHFSelectNN(Double_t a)         { m_SelectNN=a;  }

  void           CalcIPErrorMatrix();
  
  void           CalcPTMass();
  void           CalcPTMass(Int_t iseedvrt);
  
  void           CheckV0Vertex();
  Bool_t         CheckKs0Vertex(LCDVToplVRT* vrt);
  Bool_t         CheckLambda0Vertex(LCDVToplVRT* vrt);
  
  TClonesArray*  Tracks()    { return vtrack_list; }
  TClonesArray*  Vertices()  { return vertex_list; }
  TObjArray*     VrtTracks() { return vrttrack_list; }
  
  void           Clean();
  void           DeleteTracks();
  void           DeleteVertices();
  
  //Add, remove, and merge vertex...
  void           AddVertex(LCDVToplVRT*);
  void           AddVertexIntoTrack(LCDVToplTRK*,LCDVToplVRT*);
  void           AddVrtTrack(LCDVToplTRK* trk);
  void           CompressVerticesList();
  void           RemoveVertexAt(Int_t);
  void           RemoveVertex(LCDVToplVRT* vrt);
  void           MergeVertex(LCDVToplVRT* vrti,LCDVToplVRT* vrtj,Int_t f_fit);
  void           MergeVertex(Int_t i,Int_t j, Int_t f_fit);
  void           SortVertexByVsig();
  void           SortVertexByDecayLength();
  void           SortVertexByVsigInTrack(LCDVToplTRK* trk);
  void           SortVertexByVsigInAllTrack();
  
  //Topological vertex finding alghorithm.
  //all other vertices must contain at least 2 tracks and
  //are ordered according to their distance from the IP.
  Int_t          FindVertices(Int_t f_v0check);
  Int_t          FindVertices();
  
  void           Init();//Initialize...
  void           InitControlParameter();

  void           PrintOutForDebug();//Debug print out function

private:

  //-------------< Control Parameter >------------------
  //
  // general ZVTOP input
 
  // xy error on IP ellipsoid in ZVTOP, cm.
  Double_t ripe; //=3.0e-4 (default)

  // z error on IP ellipsoid in ZVTOP, cm.
  Double_t zipe; //=6.0e-4 (default)
 
  // MC=1 : include Monte Carlo information in
  // the output. 
  //    Int_t mc;
 
  // resolubility cut, can vary as 0.0 < VCUT < 1.0,
  // larger values produce more vertices.
  Double_t rcut; //=0.6 (default)
  
  // cut on the chi**2 contribution of a track to a vertex.
  Double_t xcut; //=10.0 (default)

  // Weights vertex finding probability by the
  // factor exp(-KANG*A**2) where A is the angle
  // in radians between the line joining the IP
  // to the 3D spatial co-ordinate and the jet
  // axis. (+ve values ~10 increase vertex 
  // finding efficiency in core of jet).
  Double_t kang; //=5.0 (default)
  
  // i.p track weight, weights the significance
  // of the IP, large values will tend to absorb
  // nearby vertices/fakes into the primary vertex.
  Double_t kipw; //=1.0 (default)
  
  //12 XYZ location of IP
  TVector3    ipv;
  TMatrixD    iper;
  TMatrixD    iper_inv;
    
  TVector3 bfield; //Magnetic Field Vector

  Double_t dcut; //???
  
  Int_t    nstep; //???

  //12 XYZ,magnitude of summed track momenta
  TVector3    pja;

  //
  // PT corrected mass....
  //
  
  // Cut values for Seed Vertex Finding.
  Double_t m_SeedVrtRMax;   // Rmax cut: Default 2.3
  Double_t m_SeedVrtK0Mass; // Mass cut to reject K0S: 0.015 GeV
  Double_t m_SeedVrtLambda0Mass; // Mass cut to reject K0S: 0.015 GeV
  Double_t m_SeedVrtSigMin; // Sig min cut : 2.0 sigma

  // Cut calues for track attatcement
  // Attatch track Max DOCA to vertex axis.
  Double_t m_TrdiMax; // TRDI cut : Default 0.1
  // Attatch track POCA min longi dist along VTX axis
  Double_t m_LodiMin; // Lodi cut : Default 0.05
  // Attatch track POCA min longi dist/seed vertex dist.
  Double_t m_LodrMin; // Lodr cut | Cefault 0.25
  // Attatch track POCA max longi dist/seed vertex dist.
  Double_t m_LodrMax; // Lodr cut | Cefault 2.0
  // Attatch track max angle between track and vertex direction
  Double_t m_AntaMax;
  
  // PT correction stuff
  // IP error for PT correction, xy and z
  Double_t m_PTIP[2]; // Default ~1.5 sigma ... 0.0010(xy) and 0.0040(z)
  // Number of sigma for Vertex error for PT correction
  Double_t m_NVsigma; // Default 1.0

  // NN valiables
  Bool_t   m_UseNN;      // use NN for HF-jet tag... default kFALSE.
  Double_t m_SeedVrtNN;  // NN cut for seed vertex selection... default 0.7
  Double_t m_TrackAttNN; // NN cut for track attachment... default 0.6
  Double_t m_SelectNN;   // NN cut for heavy flavour tag... default 0.5


  Int_t    dblv;  //Debug level

  //-------------< Out Parameter >------------------

  // Output from CalcPTMass
  Double_t m_Rmass    ;// Raw Mass
  Double_t m_PtMass   ;// Pt corrected Mass
  Double_t m_PtMassEr ;// Pt corrected Mass with IP errors
  Double_t m_Masstag  ;// Pt corrected IP err with 2*raw mass oritection
  Double_t m_MissPt   ;// Missing Pt
  TLorentzVector m_p4Vertex; //Four vector of the vertex
  
  TVector3    ptks;  //12 XYZ,magnitude of summed track momenta
  
  TClonesArray* vtrack_list;  // list of track objects for vertex finding.
  
  TClonesArray* vertex_list;  // list of reconstructed vertex objects
  
  TObjArray*    vrttrack_list;  // list of track objects in vertex;

public:
  ClassDef(LCDVTopl,2) // Main class for a topological vertexing.
    
};
#endif
