// LCDVToplTRKS.h
// August 15,2000 Masako & Toshi, original version copied from D.Jackson's
//                ZVTOP3
// 
#ifndef LCDVTOPLTRK_H
#define LCDVTOPLTRK_H

#include "TObjArray.h"
#include "TVector3.h"
#include "TMatrixD.h"
#include "LCDTrack.h"

class LCDVToplTRK: public TObject {
 
public:
  //constructor & deconstructor
  LCDVToplTRK();
  LCDVToplTRK(Int_t tkid, Double_t* tkpar, Double_t* e_tkpar, 
	      Double_t chrg,
	      Double_t mfld, Int_t mc_ind, const TVector3& ipv);
  LCDVToplTRK(TObjArray* trk_list,Int_t trk_id, const TVector3& ipv);
  ~LCDVToplTRK() {}
  
  Int_t      GetTrackID()               { return track_id       ; }
  Double_t   GetTrackParameter(Int_t i) { return m_trackPar[i]  ; }
  Double_t*  GetTrackParameters()       { return m_trackPar     ; }
  Double_t   GetCharge()                { return m_charge       ; }
  Double_t   GetMagneticField()         { return m_magneticfield; }
  Int_t      GetParticle()              { return m_index        ; }
  Int_t      GetTrkVal()                { return trkval         ; }
  
  Double_t   GetPositionX(Double_t l);
  Double_t   GetPositionY(Double_t l);
  Double_t   GetPositionZ(Double_t l);
  TVector3   GetPositionVector(Double_t l);
  Double_t   GetMomentumPx(Double_t l);
  Double_t   GetMomentumPy(Double_t l);
  Double_t   GetMomentumPz(Double_t l);
  TVector3   GetMomentumVector(Double_t l);
  Double_t   GetTsi(Double_t l, const TVector3& ipv);
  Double_t   GetEta(Double_t l, const TVector3& ipv);
  Double_t   GetTrackProbabirity(const TVector3& xvrt, const TVector3& ipv);
  Double_t   GetDistance(Double_t l, const TVector3& xvrt);
  Double_t   GetDistance(Double_t l,
			 Double_t x_from, Double_t y_from, Double_t z_from);
  Double_t   GetDistance2D(Double_t l,
			   Double_t x_from, Double_t y_from);
  Double_t   GetSignedDistance(const TVector3& x_from, const TVector3& pjet);
  Double_t   GetSignedDistance(Double_t l,
			       const TVector3& x_from, const TVector3& pjet);
  Double_t   GetDistanceNormByError(const TVector3& x_from);
  Double_t   GetDistanceNormByError(Double_t l, const TVector3& x_from);
  Double_t   GetDistanceNormByError(const TVector3& x_from, TMatrixD& ex_from);
  Double_t   GetDistanceNormByError(Double_t l, const TVector3& x_from, 
				    TMatrixD& ex_from);
  Double_t   GetSignedDistanceNormByError(const TVector3& x_from, 
					  const TVector3& pjet);
  Double_t   GetSignedDistanceNormByError(Double_t l, const TVector3& x_from, 
					  const TVector3& pjet);
  Double_t   GetSignedDistanceNormByError(const TVector3& x_from, 
					  const TVector3& pjet, 
					  TMatrixD& ex_from);
  Double_t   GetSignedDistanceNormByError(Double_t l,
					  const TVector3& x_from, 
					  const TVector3& pjet, 
					  TMatrixD& ex_from);
  
  Double_t   GetTrdi(Double_t l, const TVector3& ipv, const TVector3& xvrt);
  Double_t   GetTrdi(const TVector3& ipv, const TVector3& xvrt);
  Double_t   GetLodi(Double_t l, const TVector3& ipv, const TVector3& xvrt);
  Double_t   GetLodi(const TVector3& ipv, const TVector3& xvrt);
  void       GetTrdiLodi(Double_t l, const TVector3& ipv, const TVector3& xvt,
			 Double_t* trdi, Double_t* lodi);
  void       GetTrdiLodiAnta(Double_t l,
			     const TVector3& ipv, const TVector3& xvt,
			     Double_t* trdi, Double_t* lodi, Double_t* anta);
  
  Double_t   GetErrorMatrixElement(Int_t i, Int_t j);
  Double_t*  GetErrorTrackParameters() { return m_trackErrorMatrix; }
  void       GetErrorMatrix(TMatrixD& em);
  void       GetErrorMatrixPosition(Double_t l, TMatrixD& em);
  void       GetErrorMatrixMomentum(Double_t l, TMatrixD& em);
  Double_t   GetErrorTsi(Double_t l, const TVector3& ipv);
  Double_t   GetErrorTsiApprox(Double_t l);
  Double_t   GetErrorEta(Double_t l, const TVector3& ipv);
  Double_t   GetErrorEtaApprox(Double_t l);
  Double_t   GetErrorDistance(Double_t l, const TVector3& xvrt);
  Double_t   GetErrorDistance(Double_t l,
			      Double_t x_from, 
			      Double_t y_from, 
			      Double_t z_from);
  Double_t   GetErrorDistance(Double_t l, 
			      const TVector3& x_from, TMatrixD& ex_from);
  Double_t   GetErrorDistance(Double_t l,
			      Double_t x_from, 
			      Double_t y_from, 
			      Double_t z_from,
			      TMatrixD& ex_from);
  Double_t   GetErrorDistance2D(Double_t l,
				Double_t x_from, 
				Double_t y_from);
  void       GetdxdaT(Double_t l, TMatrixD& dxda);
  void       GetdpdaT(Double_t l, TMatrixD& dpda);
  void       GetdddaT(Double_t l, 
		      Double_t x_from, Double_t y_from, Double_t z_from,
		      TMatrixD& ddda);
  void       GetdddaT2D(Double_t l, 
			Double_t x_from, Double_t y_from,
			TMatrixD& ddda);
  void       Getd2xd2l(Double_t l, TMatrixD& d2xd2l);
  void       Getdxdl(Double_t l, TMatrixD& dxdl);
  TVector3   GetdxdlVector(Double_t l);
  Double_t   GetLminTrdiApprox(const TVector3& xfrom,const TVector3& xto);
  Double_t   GetLminTrdiApprox(Double_t l0,
			       const TVector3& xfrom,const TVector3& xto);
  Double_t   GetLminTrdi(const TVector3& xfrom,const TVector3& xto);
  Double_t   GetLminTrdi(Double_t l0, 
			 const TVector3& xfrom,const TVector3& xto);
  Double_t   GetdTrdi2dl(Double_t l,
			 const TVector3& xfrom, const TVector3& xto);
  Double_t   Getd2Trdi2d2l(Double_t l, 
			   const TVector3& xfrom, const TVector3& xto);
  
  
  Int_t      GetVertexEntries()   { return m_nvrt        ; }
  TObject*   GetVertexAt(Int_t i) { return vertex_list[i]; }
  
  Int_t      GetV0flag() { return v0flag; }
  
  Double_t   GetLPOCA2(const TVector3& xpt);
  
  Double_t   CalcPOCA3(Double_t l,const TVector3& xpt);
  Double_t   CalcPOCA3(const TVector3& xpt);
  
  void       SetTrkVal(Int_t a) { trkval=a; }
  void       SetV0flag(Int_t a) { v0flag=a; }

  TObject** Vertices() { return vertex_list; };
  
  void       AddVertex(TObject*);
  void       AddVertexAt(TObject*,Int_t);
  void       RemoveVertex(TObject*);
  void       RemoveVertexAt(Int_t);
  void       CompressVerticesList();

  Double_t   dlen2(Double_t, const TVector3&);
  Double_t   ddlen2dl(Double_t,const TVector3&);
  Double_t   d2dlen2d2l(Double_t, const TVector3&);

private:
  //id of track of LCDTrack
  Int_t       track_id;   
  
  // helix parameters
  Double_t m_trackPar[5];
  /* 0     d0
     1     phi0
     2   omega=(-Q/rho) <0  charge +   
     >0  charge -
     3     z0
     4     s(=tan_L)                       */

  // error matrix of helix parameters
  Double_t m_trackErrorMatrix[15]; 
  // m_trackErrorMatrix[ 0] = sigma(0)*sigma(0)
  // m_trackErrorMatrix[ 1] = sigma(1)*sigma(0)
  // m_trackErrorMatrix[ 2] = sigma(1)*sigma(1)
  // m_trackErrorMatrix[ 3] = sigma(2)*sigma(0)
  // m_trackErrorMatrix[ 4] = sigma(2)*sigma(1)
  // m_trackErrorMatrix[ 5] = sigma(2)*sigma(2)
  // m_trackErrorMatrix[ 6] = sigma(3)*sigma(0)
  // m_trackErrorMatrix[ 7] = sigma(3)*sigma(1)
  // m_trackErrorMatrix[ 8] = sigma(3)*sigma(2)
  // m_trackErrorMatrix[ 9] = sigma(3)*sigma(3)
  // m_trackErrorMatrix[10] = sigma(4)*sigma(0)
  // m_trackErrorMatrix[11] = sigma(4)*sigma(1)
  // m_trackErrorMatrix[12] = sigma(4)*sigma(2)
  // m_trackErrorMatrix[13] = sigma(4)*sigma(3)
  // m_trackErrorMatrix[14] = sigma(4)*sigma(4)

  Double_t m_charge;     // Charge of the particle
  Double_t m_magneticfield;
  Int_t m_index;        // Index to the McPart object responsible for the track
  
  Int_t m_nvrt;
  TObject* vertex_list[100];

  Int_t trkval; //if seed=1, attached=2, else =0

  Double_t rmax;
  Double_t err_tsi[3]; //error**2 of tsi at CA.
  Double_t err_eta[3]; //error**2 of eta at CA.

  Int_t v0flag; //if =1:gamma conversion =2:k0s =3:lambda

  void Init(); //Initialize.

  void Init(Int_t tkid, Double_t* tkpar, Double_t* e_tkpar, 
	    Double_t chrg, Double_t mfld, Int_t mc_ind,
	    const TVector3& ipv); //Initialize.

public:
  ClassDef(LCDVToplTRK,2) // a track class for topological vertexing.

};

#endif
