// LCDVToplTRKS.h
// August 15,2000 Masako & Toshi, original version copied from D.Jackson's
//                ZVTOP3
// 
#ifndef LCDVTOPLTRK_H
#define LCDVTOPLTRK_H

#include "TMath.h"
#include "TObject.h"
#include "TObjArray.h"
#include "TVector3.h"
#include "TMatrixD.h"
#include "LCDTrack.h"

class LCDVToplTRK: public TObject {
 
 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

  //distance in cm from the track to the IP
  //if no secondary vertex is found, otherwise
  //the closest approach of the track to the
  //line 2.5 cm long from the IP passing through
  //the 'secondary' vertex furthest from the 
  //IP, - intended to check if isolated tracks
  //are consistent with the decay chain
  //  Double_t    trdi;
  
  //distance from IP along 2.5 cm line to TRDI
  //  Double_t    lodi;
  
  TObjArray* vertex_list;

  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 Initialize(); //Initialize.

  void Initialize(Int_t tkid, Double_t* tkpar, Double_t* e_tkpar, 
		  Double_t chrg, Double_t mfld, Int_t mc_ind,
		  TVector3 ipv); //Initialize.
 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,TVector3 ipv);
  LCDVToplTRK(TObjArray* trk_list,Int_t trk_id,TVector3 ipv);
  ~LCDVToplTRK();

  Int_t      GetTrackID()       { return track_id; }
  Double_t   GetTrackParameter(Int_t i);
  Double_t*  GetTrackParameters();
  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, TVector3 ipv);
  Double_t   GetEta(Double_t l, TVector3 ipv);
  Double_t   GetTrackProbabirity(TVector3 xvrt, TVector3 ipv);
  Double_t   GetDistance(Double_t l, 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(TVector3 x_from, TVector3 pjet);
  Double_t   GetSignedDistance(Double_t l, TVector3 x_from, TVector3 pjet);
  Double_t   GetDistanceNormByError(TVector3 x_from);
  Double_t   GetDistanceNormByError(Double_t l, TVector3 x_from);
  Double_t   GetDistanceNormByError(TVector3 x_from, TMatrixD& ex_from);
  Double_t   GetDistanceNormByError(Double_t l, TVector3 x_from, 
				    TMatrixD& ex_from);
  Double_t   GetSignedDistanceNormByError(TVector3 x_from, 
					  TVector3 pjet);
  Double_t   GetSignedDistanceNormByError(Double_t l, TVector3 x_from, 
					  TVector3 pjet);
  Double_t   GetSignedDistanceNormByError(TVector3 x_from, 
					  TVector3 pjet, TMatrixD& ex_from);
  Double_t   GetSignedDistanceNormByError(Double_t l, TVector3 x_from, 
					  TVector3 pjet, TMatrixD& ex_from);
  
  Double_t   GetTrdi(Double_t l, TVector3 ipv, TVector3 xvrt);
  Double_t   GetTrdi(TVector3 ipv, TVector3 xvrt);
  Double_t   GetLodi(Double_t l, TVector3 ipv, TVector3 xvrt);
  Double_t   GetLodi(TVector3 ipv, TVector3 xvrt);
  void       GetTrdiLodi(Double_t l, TVector3 ipv, TVector3 xvt,
			 Double_t* trdi, Double_t* lodi);
  void       GetTrdiLodiAnta(Double_t l, TVector3 ipv, 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, TVector3 ipv);
  Double_t   GetErrorTsiApprox(Double_t l);
  Double_t   GetErrorEta(Double_t l, TVector3 ipv);
  Double_t   GetErrorEtaApprox(Double_t l);
  Double_t   GetErrorDistance(Double_t l, 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, 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(TVector3 xfrom,TVector3 xto);
  Double_t   GetLminTrdiApprox(Double_t l0, TVector3 xfrom,TVector3 xto);
  Double_t   GetLminTrdi(TVector3 xfrom,TVector3 xto);
  Double_t   GetLminTrdi(Double_t l0, TVector3 xfrom,TVector3 xto);
  Double_t   GetdTrdi2dl(Double_t l, TVector3 xfrom, TVector3 xto);
  Double_t   Getd2Trdi2d2l(Double_t l, TVector3 xfrom, TVector3 xto);


  Int_t      GetVertexEntries();
  TObject*   GetVertexAt(Int_t);

  Int_t      GetV0flag() { return v0flag; }

  Double_t   GetLPOCA2(TVector3 xpt);

  Double_t   CalcPOCA3(Double_t l,TVector3 xpt);
  Double_t   CalcPOCA3(TVector3 xpt);

  void       SetTrkVal(Int_t a) { trkval=a; }
  void       SetV0flag(Int_t a) { v0flag=a; }

  TObjArray* 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, TVector3);
  Double_t   ddlen2dl(Double_t,TVector3);
  Double_t   d2dlen2d2l(Double_t, TVector3);

  ClassDef(LCDVToplTRK,2) // a track class for topological vertexing.

};

#endif
