#include <TTreeStream.h>
#include "AliESDEvent.h"
#include "AliTPCseed.h"
#include "AliTrackerBase.h"
#include "AliESDCosmicTrack.h"
#include "AliCosmicTracker.h"
#include "AliTPCCosmicUtils.h"
#include "AliTPCCosmicTrackfit.h"
AliCosmicTracker::AliCosmicTracker(const Int_t dlev, const TString tag):
fUserCut(0x0)
, fStreamer(0x0), fDebugLevel(dlev)
, fESDEvent(0x0)
, fCosmicTrackfit(0x0)
, fTrackStack(0x0)
, fTrack0()
, fTrack1()
, fRawVtx(-999,-999,-999)
, fRawDCA(-999)
, fdPhi(-999)
, fCutdPhi(-999)
, fdTheta(-999)
, fCutdTheta(-999)
, fErrFlagESDtrackCut(-999)
, fErrFlagIsPair(-999)
, fErrFlagCosmicTrackfit(-999)
{
if(fDebugLevel & 1)
fStreamer = new TTreeSRedirector(Form("CosmicTracker_%s.root", tag.Data()));
fCosmicTrackfit = new AliTPCCosmicTrackfit(0, "AliCosmicTracker");
fTrackStack = new TClonesArray("AliESDCosmicTrack",100);
for(Int_t ii=0; ii<5; ii++){
fDelta[ii] = -999;
fPull[ii] = -999;
}
fCutdPhi = 19e-3*5;
fCutdTheta = 10e-3*5;
fCutPull[0] = 1.9 *10;
fCutPull[1] = 1.5 *1e10;
fCutPull[2] = 1.9 *10;
fCutPull[3] = 0.4 *1e10;
fCutPull[4] = 3.6 *10;
fCutDelta[0] = 0.8 * 10;
fCutDelta[1] = 2.7 * 10;
fCutDelta[2] = 0.012 * 10;
fCutDelta[3] = 0.007 * 10;
fCutDelta[4] = 0.05 * 10;
}
AliCosmicTracker::~AliCosmicTracker()
{
delete fStreamer;
delete fCosmicTrackfit;
delete fTrackStack;
}
void AliCosmicTracker::SetESDEvent(AliESDEvent *esd)
{
fESDEvent = esd;
fTrackStack->Clear();
}
Int_t AliCosmicTracker::Process(const TString tag, const Bool_t kprint)
{
Int_t npair=0;
const Int_t ntrk = fESDEvent->GetNumberOfTracks();
Int_t trkcounter[ntrk];
for(Int_t ii=0; ii<ntrk; ii++){
trkcounter[ii]=0;
}
Double_t findabler0 = -999;
Double_t findabler1 = -999;
fErrFlagESDtrackCut = 0;
fErrFlagIsPair = 0;
fErrFlagCosmicTrackfit = 0;
for(Int_t itrk=0; itrk<ntrk; itrk++){
if(!ESDtrackCut(fESDEvent->GetTrack(itrk), findabler0)){
continue;
}
for(Int_t jtrk=itrk+1; jtrk<ntrk; jtrk++){
if(!ESDtrackCut(fESDEvent->GetTrack(jtrk), findabler1))
continue;
AliESDtrack * trk0 = fESDEvent->GetTrack(itrk);
AliESDtrack * trk1 = fESDEvent->GetTrack(jtrk);
if( IsPair(trk0, trk1) ){
const Bool_t kfit = fCosmicTrackfit->CombineESDtracks(trk0, trk1);
fErrFlagCosmicTrackfit = fCosmicTrackfit->GetStatus();
if(kfit){
fRawVtx = fCosmicTrackfit->ImpactParameter3D();
fRawDCA = fCosmicTrackfit->ImpactParameter2D().Mag();
const Int_t ncls = fCosmicTrackfit->GetFitNcls();
const Double_t leverarm = fCosmicTrackfit->GetFitLeverArm();
const Double_t chi2percluster = fCosmicTrackfit->GetChi2PerCluster();
const Double_t impactD = fCosmicTrackfit->GetImpactD();
const Double_t impactZ = fCosmicTrackfit->GetImpactZ();
const Double_t findableratio = TMath::Min(findabler0, findabler1);
trkcounter[itrk]++;
trkcounter[jtrk]++;
const Bool_t isreuse = (trkcounter[itrk]>1 || trkcounter[jtrk]>1);
const TVector3 icU = fCosmicTrackfit->GetInnerClusterUp();
const TVector3 icD = fCosmicTrackfit->GetInnerClusterLow();
Int_t idup = itrk;
Int_t idlow = jtrk;
if(fCosmicTrackfit->IsSwap()){
const Int_t idtmp = idup;
idup = idlow;
idlow = idtmp;
AliExternalTrackParam tptmp = fTrack0;
fTrack0 = fTrack1;
fTrack1 = tptmp;
}
if(
(fDebugLevel & 4) &&
( (isreuse && ntrk<=4) || kprint )
){
AliESDtrack * trks[]={fESDEvent->GetTrack(idup), fESDEvent->GetTrack(idlow)};
AliTPCCosmicUtils::DrawTracks(trks, Form("reuse_%03d_%03d_%03d_%s", ntrk, itrk, jtrk, tag.Data()));
}
if(
(fDebugLevel & 8) &&
impactD > 160 && findableratio < 0.56
){
AliESDtrack * trks[]={fESDEvent->GetTrack(idup), fESDEvent->GetTrack(idlow)};
AliTPCCosmicUtils::DrawTracks(trks, Form("largevtd_%.f_%.f_%03d_%03d_%03d_%s", impactD, findableratio, ntrk, itrk, jtrk, tag.Data()));
}
AliESDCosmicTrack costrk(idup, idlow, fCosmicTrackfit->GetTrackParamUp(), fCosmicTrackfit->GetTrackParamLow(), &fTrack0, &fTrack1, ncls, leverarm, chi2percluster, impactD, impactZ, isreuse, findableratio, icU, icD);
new((*fTrackStack)[npair]) AliESDCosmicTrack(costrk);
npair++;
if(fDebugLevel & 1)
WriteStreamer(ntrk, &costrk);
}
else{
if(fDebugLevel & 16){
if(ntrk==2){
AliESDtrack * trks[]={trk0, trk1};
AliTPCCosmicUtils::DrawTracks(trks, Form("failCosmicFit_%02d_%03d_%03d_%03d_%s", fCosmicTrackfit->GetStatus(), ntrk, itrk, jtrk, tag.Data()));
}
}
}
}
else{
if(fDebugLevel & 32){
if(ntrk==2){
AliESDtrack * trks[]={trk0, trk1};
AliTPCCosmicUtils::DrawTracks(trks, Form("failIsPair_%02d_%03d_%03d_%03d_%s", fErrFlagIsPair, ntrk, itrk, jtrk, tag.Data()));
}
}
}
}
}
return npair;
}
Bool_t AliCosmicTracker::IsPair(AliESDtrack * trk0, AliESDtrack * trk1)
{
fdPhi = AliTPCCosmicUtils::AngleInRange(trk0->Phi() - trk1->Phi() + TMath::Pi());
if( TMath::Abs(fdPhi) > fCutdPhi ){
fErrFlagIsPair = 1;
return kFALSE;
}
fdTheta = AliTPCCosmicUtils::AngleInRange(trk0->Theta() + trk1->Theta() + TMath::Pi());
if( TMath::Abs(fdTheta) > fCutdTheta ){
fErrFlagIsPair = 2;
return kFALSE;
}
if(!trk0->GetInnerParam()){
fErrFlagIsPair = 3;
return kFALSE;
}
if(!trk1->GetInnerParam()){
fErrFlagIsPair = 4;
return kFALSE;
}
AliExternalTrackParam tmptrk[]={*(trk0->GetInnerParam()), *(trk1->GetInnerParam())};
if(fDebugLevel & 2){
printf("\n************************ raw ESD:\n");
AliTPCCosmicUtils::PrintTrackParam(100, &(tmptrk[0]));
AliTPCCosmicUtils::PrintTrackParam(101, &(tmptrk[1]));
tmptrk[0].Print();
tmptrk[1].Print();
}
Double_t xyz0[3], xyz1[3];
tmptrk[0].GetXYZ(xyz0);
tmptrk[1].GetXYZ(xyz1);
const TVector3 gpos0(xyz0), gpos1(xyz1);
const Double_t meanalpha = (gpos0-gpos1).Phi();
const Double_t alpha0 = tmptrk[0].GetAlpha();
if( TMath::Abs(AliTPCCosmicUtils::AngleInRange(meanalpha-alpha0)) <TMath::PiOver2() ){
if( !AliTPCCosmicUtils::RotateSafe(&(tmptrk[0]), meanalpha) ||
!AliTPCCosmicUtils::RotateSafe(&(tmptrk[1]), meanalpha+TMath::Pi()) ){
fErrFlagIsPair = 5;
return kFALSE;
}
}
else{
if( !AliTPCCosmicUtils::RotateSafe(&(tmptrk[1]), meanalpha) ||
!AliTPCCosmicUtils::RotateSafe(&(tmptrk[0]), meanalpha+TMath::Pi()) ){
fErrFlagIsPair = 6;
return kFALSE;
}
}
if(fDebugLevel & 2){
printf("\n************************ after rotation!!\n");
AliTPCCosmicUtils::PrintTrackParam(300, &(tmptrk[0]));
AliTPCCosmicUtils::PrintTrackParam(301, &(tmptrk[1]));
tmptrk[0].Print();
tmptrk[1].Print();
}
const Double_t xTogo = 0.0;
const Double_t maxStep = 1;
const Bool_t rotateTo = kFALSE;
const Double_t maxSnp = 0.8;
Double_t eloss[2]={-1, 1};
if(AliTPCCosmicUtils::AngleInRange(tmptrk[0].Phi())<0){
eloss[0]= 1;
eloss[1]=-1;
}
for(Int_t ii=0; ii<2; ii++){
if(!AliTrackerBase::PropagateTrackToBxByBz(&(tmptrk[ii]), xTogo, AliTPCCosmicUtils::Mass(), maxStep, rotateTo, maxSnp, (Int_t)(eloss[ii]))){
fErrFlagIsPair = 7;
return kFALSE;
}
}
if(fDebugLevel & 2){
printf("\n************************ after dedx corr:\n");
AliTPCCosmicUtils::PrintTrackParam(200, &(tmptrk[0]));
AliTPCCosmicUtils::PrintTrackParam(201, &(tmptrk[1]));
tmptrk[0].Print();
tmptrk[1].Print();
}
fDelta[0] = tmptrk[0].GetParameter()[0] + tmptrk[1].GetParameter()[0];
fDelta[1] = tmptrk[0].GetParameter()[1] - tmptrk[1].GetParameter()[1];
fDelta[2] = tmptrk[0].GetParameter()[2] - tmptrk[1].GetParameter()[2];
fDelta[3] = tmptrk[0].GetParameter()[3] + tmptrk[1].GetParameter()[3];
fDelta[4] = tmptrk[0].GetParameter()[4] + tmptrk[1].GetParameter()[4];
fPull[0] = fDelta[0]/TMath::Sqrt(tmptrk[0].GetCovariance()[0] +tmptrk[1].GetCovariance()[0]);
fPull[1] = fDelta[1]/TMath::Sqrt(tmptrk[0].GetCovariance()[2] +tmptrk[1].GetCovariance()[2]);
fPull[2] = fDelta[2]/TMath::Sqrt(tmptrk[0].GetCovariance()[5] +tmptrk[1].GetCovariance()[5]);
fPull[3] = fDelta[3]/TMath::Sqrt(tmptrk[0].GetCovariance()[9] +tmptrk[1].GetCovariance()[9]);
fPull[4] = fDelta[4]/TMath::Sqrt(tmptrk[0].GetCovariance()[14]+tmptrk[1].GetCovariance()[14]);
if(fDebugLevel & 2){
for(Int_t ii=0; ii<5; ii++){
printf("test %d %e %e -- %e\n", ii, tmptrk[0].GetParameter()[ii], tmptrk[1].GetParameter()[ii], fPull[ii]);
}
}
for(Int_t ii=0; ii<5; ii++){
if( TMath::Abs(fPull[ii]) > fCutPull[ii] ){
fErrFlagIsPair = 10+ii;
return kFALSE;
}
if( TMath::Abs(fDelta[ii]) > fCutDelta[ii] ){
fErrFlagIsPair = 20+ii;
return kFALSE;
}
}
fTrack0 = tmptrk[0];
fTrack1 = tmptrk[1];
return kTRUE;
}
Bool_t AliCosmicTracker::ESDtrackCut(AliESDtrack * trk, Double_t &findabler)
{
if(fUserCut){
if(!fUserCut(trk)){
fErrFlagESDtrackCut = 1;
return kFALSE;
}
}
if(trk->GetKinkIndex(0)>0){
fErrFlagESDtrackCut = 2;
return kFALSE;
}
if(!trk->IsOn(AliESDtrack::kTPCrefit)){
fErrFlagESDtrackCut = 3;
return kFALSE;
}
findabler = -999;
if(!trk->GetTPCNclsF()){
fErrFlagESDtrackCut = 4;
return kFALSE;
}
findabler = (Double_t)trk->GetTPCNcls()/(Double_t) trk->GetTPCNclsF();
if(findabler < CutFindable() ){
fErrFlagESDtrackCut = 5;
return kFALSE;
}
if(trk->GetTPCncls()<AliTPCCosmicUtils::NclsMin()){
fErrFlagESDtrackCut = 6;
return kFALSE;
}
if(!AliTPCCosmicUtils::GetTPCseed(trk)){
fErrFlagESDtrackCut = 7;
return kFALSE;
}
return kTRUE;
}
Int_t AliCosmicTracker::GetErrFlag() const
{
return fErrFlagESDtrackCut + fErrFlagIsPair*100 + fErrFlagCosmicTrackfit*10000;
}
void AliCosmicTracker::WriteStreamer(Int_t ntrk, AliESDCosmicTrack *costrk)
{
(*fStreamer)<<"CosmicTracker_Streamer"<<
"ntrk="<<ntrk<<
"costrk="<<costrk<<
"rawvtx="<<&fRawVtx<<
"rawdca="<<fRawDCA<<
"dphi="<<fdPhi<<
"dtheta="<<fdTheta<<
"pull0="<<fPull[0]<<
"pull1="<<fPull[1]<<
"pull2="<<fPull[2]<<
"pull3="<<fPull[3]<<
"pull4="<<fPull[4]<<
"delta0="<<fDelta[0]<<
"delta1="<<fDelta[1]<<
"delta2="<<fDelta[2]<<
"delta3="<<fDelta[3]<<
"delta4="<<fDelta[4]<<
"\n";
}
TClonesArray *AliCosmicTracker::FindCosmic(AliESDEvent *event, const Bool_t kadd)
{
AliCosmicTracker cosmicTracker;
cosmicTracker.SetESDEvent(event);
const Int_t npair = cosmicTracker.Process();
const TClonesArray *arr = cosmicTracker.GetTrackStack();
TClonesArray *stackCosmic = 0x0;
if(kadd){
for(Int_t ip=0; ip<npair; ip++){
const AliESDCosmicTrack * esdcos = (AliESDCosmicTrack*) arr->At(ip);
event->AddCosmicTrack(esdcos);
}
printf("AliCosmicTracker::FindCosmic: event %d: Number of cosmic pairs by AliCosmicTracker %d out of %d tracks, err %d\n", event->GetEventNumberInFile(), npair, event->GetNumberOfTracks(), cosmicTracker.GetErrFlag());
}
else{
stackCosmic = new TClonesArray(*arr);
}
return stackCosmic;
}