4 // Macro to compare tracks used 2 different reconstruction algorithms (Offline and HLT)
5 // (In general the approach can be used for any pair of the esds - track containers)
7 // Main functions - Dump content of HLT and OFFLINE esd files - full esd tracks
8 // 1. Dump to the tree the pair of close tracks ( n sigma distance at the TPC entrance)
9 // 2. Dump to the tree the track and corrsponding counter of tracks from other container
10 // Compare two events - track by track comparison
11 // 0. Filter "Good" tpc tracks - see function IsSelected(track)
12 // 1. Dump OFFline -> HLT tracks into trees
13 // a.) tree "offhlt" - counters+ Ofline track + corresponding Hlt track
14 // b.) tree "offhlt0" - offline track + hlt track counter
17 // 3. To save the CPU and disk space the input tracks to compare are pt downscaled
18 // see function IsDownscaled();
20 // Visualization part is currently work in progress
23 // dumping part: marian.ivanov@cern.ch
24 // visualization part:
27 aliroot -b -q $ALICE_ROOT/TPC/macros/compareTracks.C+
31 gSystem->Load("libANALYSIS");
32 gSystem->Load("libANALYSISalice");
33 gSystem->Load("libPWG0base");
34 gSystem->Load("libPWG0dep");
35 gSystem->Load("libPWG0selectors");
36 .L $ALICE_ROOT/PWG1/TPC/macros/compareTracks.C+
38 compareTracks("compare.list");
48 #include "TStopwatch.h"
50 #include "AliESDEvent.h"
51 #include "TTreeStream.h"
53 #include "AliXRDPROOFtoolkit.h"
54 #include "AliSysInfo.h"
59 void CompareFile(TTreeSRedirector *pcstream, TFile *fOff, TFile *fHLT);
60 void CompareEvents(AliESDEvent *evoff, AliESDEvent *evhlt, TTreeSRedirector *pcstream);
61 Bool_t AreTracksCloseFast(AliESDtrack *track1, AliESDtrack *track2, AliESDEvent * event, AliExternalTrackParam &inner2);
62 Bool_t IsSelected(AliESDtrack *track);
63 Bool_t IsDownscaled(AliESDtrack *track);
65 Double_t gptdownscale=100; //pt downscale parameter
67 TTree * chainOFFHLT=0;
68 TTree * chainOFFHLT0=0;
69 TTree * chainHLTOFF=0;
70 TTree * chainHLTOFF0=0;
72 void compareTracks(const char * flistOFF="compareOFF.list", const char * flistHLT="compareHLT.list", Double_t downscale=10000){
74 // Compare HLT and OFFLINE esd files
76 // flist - the ascii files with the filename - ESD form the offline
77 // - hlt path constructed from the offline ESD file repalcing the OFFLINE with HLT
79 gptdownscale=downscale;
80 TTreeSRedirector *pcstream = new TTreeSRedirector("dump.root");
87 // Read the input list of files and add them to the chain
88 TString currentFileOff;
89 TString currentFileHlt;
90 { while( (inOFF.good()) && (inHLT.good())) {
91 inOFF >> currentFileOff;
92 inHLT >> currentFileHlt;
93 //currentFileHlt=currentFileOff;
94 //currentFileHlt.ReplaceAll("/OFFLINE/","/HLT/");
95 printf("%s\n%s\n\n",currentFileOff.Data(), currentFileHlt.Data());
96 TFile *fOff = TFile::Open(currentFileOff.Data(),"READ");
97 TFile *fHlt = TFile::Open(currentFileHlt.Data(),"READ");
99 CompareFile(pcstream, fOff, fHlt);
106 * TTreeSRedirector *pcstream = new TTreeSRedirector("dump.root");
107 * TFile *fOff = TFile::Open("/lustre/alice/mknichel/cpass1/2011-12-13_0154/OFFLINE/167693/11000167693001.11/AliESDs.root","READ");
108 * TFile *fHLT = TFile::Open("/lustre/alice/mknichel/cpass1/2011-12-13_0154/HLT/167693/11000167693001.11/AliESDs.root","READ");
109 * CompareFile(pcstream, fOff, fHLT);
114 void CompareFile(TTreeSRedirector *pcstream, TFile *fOff, TFile *fHLT){
116 // Compare 2 esd files - fOff and fHLT
117 // Pairs of tracks dumpt in the trees - stored in the filee connected to the pcstream
119 TTree *tOff = (TTree*)fOff->Get("esdTree");
120 TTree *tHLT = (TTree*)fHLT->Get("esdTree");
122 Int_t nevents=tOff->GetEntries();
124 AliESDEvent *evoff = new AliESDEvent();
125 AliESDEvent *evhlt = new AliESDEvent();
126 evoff->ReadFromTree(tOff);
127 evhlt->ReadFromTree(tHLT);
129 for(Long64_t iev = 0; iev < nevents; iev++){
132 CompareEvents(evoff,evhlt,pcstream);
133 AliSysInfo::AddStamp(fOff->GetName(),iev);
141 void CompareEvents(AliESDEvent *evoff, AliESDEvent *evhlt, TTreeSRedirector *pcstream){
143 // Main function to dump events:
145 // compare two events - track by track comparison
146 // 0. Filter "Good" tpc tracks - see function IsSelected(track)
147 // 1. Dump OFFline -> HLT tracks into trees
148 // a.) tree "offhlt" - counters+ Ofline track + corresponding Hlt track
149 // b.) tree "offhlt" - counters +Offline track
150 // 2. HLT and offline
152 // 3. To save the CPU and disk space the input tracks to compare are pt downscaled
153 // see function Isdownscaled();
155 Int_t nOffTracks = evoff->GetNumberOfTracks();
156 Int_t nHLTTracks = evhlt->GetNumberOfTracks();
157 Int_t iev= evoff->GetEventNumberInFile();
158 if (nOffTracks==0) return;
159 AliESDtrack *offlinetrack=0, *hlttrack=0;
160 Double_t predchi2 = 0;
161 //for(Long64_t iev = 120; iev < 125; iev++)
162 TObjArray arrayOFF(20000);
163 TObjArray arrayHLT(20000);
164 AliExternalTrackParam inner2; //working track ref
171 for(Int_t ioff = 0; ioff < nOffTracks; ioff++){
172 offlinetrack = evoff->GetTrack(ioff);
173 if (!IsSelected(offlinetrack)) continue;
174 arrayOFF.AddAt(offlinetrack,nselOFF);
178 for(Int_t ihlt = 0; ihlt< nHLTTracks; ihlt++){
179 hlttrack = evhlt->GetTrack(ihlt);
180 if (!IsSelected(hlttrack)) continue;
181 arrayHLT.AddAt(hlttrack,nselHLT);
184 printf("%d\t%d\t%d\t%d\n", nOffTracks, nselOFF, nHLTTracks, nselHLT);
186 // - compare offline - hlt
189 for (Int_t ioff = 0; ioff < nselOFF; ioff++){
190 offlinetrack = (AliESDtrack*)arrayOFF.At(ioff);
191 Float_t ncl21off= offlinetrack->GetTPCClusterInfo(2,1);
192 Float_t ncl20off= offlinetrack->GetTPCClusterInfo(2,0);
193 if (IsDownscaled(offlinetrack)) continue;
196 for(Int_t ihlt = 0; ihlt < nselHLT; ihlt++){
197 hlttrack = (AliESDtrack*)arrayHLT.At(ihlt);
198 Bool_t close = AreTracksCloseFast(offlinetrack,hlttrack,evhlt,inner2);
200 Float_t ncl21hlt= hlttrack->GetTPCClusterInfo(2,1);
201 Float_t ncl20hlt= hlttrack->GetTPCClusterInfo(2,0);
203 predchi2=offlinetrack->GetInnerParam()->GetPredictedChi2(&inner2);
204 (*pcstream)<<"offhlt"<<
208 "ncl20off="<<ncl20off<<
209 "ncl21off="<<ncl21off<<
210 "ncl20hlt="<<ncl20hlt<<
211 "ncl21hlt="<<ncl21hlt<<
212 "counter="<<counter<<
215 "track1.="<<offlinetrack<<
216 "track2.="<<hlttrack<<
217 "inner2.="<<&inner2<<
221 Bool_t isDownscaled=IsDownscaled(offlinetrack);
222 (*pcstream)<<"offhlt0"<<
229 "track.="<<offlinetrack<<
230 "counter="<<counter<<
231 "isDownscaled="<<isDownscaled<<
236 for(Int_t ihlt = 0; ihlt < nselHLT; ihlt++){
238 hlttrack = (AliESDtrack*)arrayHLT.At(ihlt);
239 Float_t ncl21hlt= hlttrack->GetTPCClusterInfo(2,1);
240 Float_t ncl20hlt= hlttrack->GetTPCClusterInfo(2,0);
241 if (IsDownscaled(hlttrack)) continue;
242 for (Int_t ioff = 0; ioff < nselOFF; ioff++){
243 offlinetrack = (AliESDtrack*)arrayOFF.At(ioff);
244 Bool_t close = AreTracksCloseFast(hlttrack,offlinetrack,evhlt,inner2);
246 Float_t ncl21off= offlinetrack->GetTPCClusterInfo(2,1);
247 Float_t ncl20off= offlinetrack->GetTPCClusterInfo(2,0);
248 predchi2=hlttrack->GetInnerParam()->GetPredictedChi2(&inner2);
250 (*pcstream)<<"hltoff"<<
254 "ncl20off="<<ncl20off<<
255 "ncl21off="<<ncl21off<<
256 "ncl20hlt="<<ncl20hlt<<
257 "ncl21hlt="<<ncl21hlt<<
258 "counter="<<counter<<
261 "track2.="<<offlinetrack<<
262 "track1.="<<hlttrack<<
263 "inner2.="<<&inner2<<
267 Bool_t isDownscaled=IsDownscaled(hlttrack);
268 (*pcstream)<<"hltoff0"<<
275 "track.="<<hlttrack<<
276 "counter="<<counter<<
277 "isDownscaled="<<isDownscaled<<
283 Bool_t IsSelected(AliESDtrack *track){
286 // philipp.luettig@cern.ch
289 if (track->IsOn(0x40)==0) return kFALSE; // Refit
290 if (TMath::Abs(track->GetTgl())>1.1) return kFALSE; // tangent lambda
291 if (track->GetTPCClusterInfo(2,1)<50) return kFALSE; // cluster information number of crossed rows >50
295 Bool_t IsDownscaled(AliESDtrack *track){
297 // Downscale randomly low pt tracks
300 Double_t scalempt= TMath::Min(1./TMath::Abs(track->GetParameter()[4]),10.);
301 if (TMath::Exp(2*scalempt)<gptdownscale*gRandom->Rndm()) return kTRUE;
306 Bool_t AreTracksCloseFast(AliESDtrack *track1, AliESDtrack *track2, AliESDEvent * event, AliExternalTrackParam &inner2){
309 // Fast comparison uning track param close to the prim vertex and at the inner wall of the TPC
311 // 1. Fast cut on the invariant (under rotation) variable P3 and P4 (means pz/pt and 1/pt)
312 // 2. Slower cuts - parameters at the entrance of the TPC (tracks to be propagated)
314 // In case the tracks are relativelaly close -the inner2 parameters are created
315 // -track 2 propagated and rotated to the same position as the track1
317 const Double_t absCut[5] ={5,10, 0.02,0.02,1}; // abs cut values
318 const Double_t pullCut[5]={6,100,6, 100,6}; // pull cut values
319 // * "External" track parametrisation class *
321 // * external param0: local Y-coordinate of a track (cm) *
322 // * external param1: local Z-coordinate of a track (cm) *
323 // * external param2: local sine of the track momentum azimuthal angle *
324 // * external param3: tangent of the track momentum dip angle *
325 // * external param4: 1/pt (1/(GeV/c)) *
329 const Double_t kTglCut=0.1;
330 const Double_t k1PtCut=0.5;
331 // const Double_t kAlphaCut=0.2;
332 const Double_t kTglCutSigma=10;
333 const Double_t k1PtCutSigma=10;
336 if(!track1) return kFALSE;
337 if(!track2) return kFALSE;
338 const Double_t *param1 = track1->GetParameter();
339 const Double_t *param2 = track2->GetParameter();
340 const Double_t *param1I = track1->GetInnerParam()->GetParameter();
341 const Double_t *param2I = track2->GetInnerParam()->GetParameter();
342 const Double_t *covar1 = track1->GetCovariance();
343 const Double_t *covar2 = track2->GetCovariance();
344 const Double_t *covar1I = track1->GetInnerParam()->GetCovariance();
345 const Double_t *covar2I = track2->GetInnerParam()->GetCovariance();
347 if (TMath::Abs(param1[3]-param2[3])>kTglCut) return kFALSE;
348 //if (TMath::Abs(param1[4]-param2[4])>k1PtCut) return kFALSE;
349 if (TMath::Abs(param1I[3]-param2I[3])>kTglCut) return kFALSE;
350 if (TMath::Abs(param1I[4]-param2I[4])>k1PtCut) return kFALSE;
351 Double_t dalpha = TMath::Abs(track1->GetAlpha()-track2->GetAlpha());
352 if (dalpha>TMath::Pi()) dalpha-=TMath::Abs(dalpha-TMath::TwoPi());
353 //if (dalpha > kAlphaCut) return kFALSE;
356 Int_t index22=track1->GetIndex(2,2);
357 Int_t index33=track1->GetIndex(3,3);
358 Int_t index44=track1->GetIndex(4,4);
359 if (TMath::Abs(param1[3]-param2[3])/TMath::Sqrt(TMath::Max(covar1[index33],covar2[index33]))>kTglCutSigma) return kFALSE;
360 //if (TMath::Abs(param1[4]-param2[4])/TMath::Sqrt(TMath::Max(covar1[index44],covar2[index44]))>k1PtCutSigma) return kFALSE;
361 if (TMath::Abs(param1I[3]-param2I[3])/TMath::Sqrt(TMath::Max(covar1I[index33],covar2I[index33]))>kTglCutSigma) return kFALSE;
362 if (TMath::Abs(param1I[4]-param2I[4])/TMath::Sqrt(TMath::Max(covar1I[index44],covar2I[index44]))>k1PtCutSigma) return kFALSE;
363 if (TMath::Abs(dalpha)/TMath::Sqrt(TMath::Max(covar1[index22],covar2[index22]))>k1PtCutSigma) return kFALSE;
365 // 2. Slow cuts on the paramters at the entrance of the TPC
367 inner2=*(track2->GetInnerParam());
368 inner2.Rotate(track1->GetInnerParam()->GetAlpha());
369 inner2.PropagateTo(track1->GetInnerParam()->GetX(), event->GetMagneticField());
370 const Double_t *pinner2 = inner2.GetParameter();
371 const Double_t *pcovar2 = inner2.GetCovariance();
374 for (Int_t ipar=0; ipar<5; ipar++){
376 Int_t index=track1->GetIndex(ipar,ipar);
377 if (TMath::Abs(pinner2[ipar]-param1I[ipar])>absCut[ipar]) isOK=kFALSE;
378 if (TMath::Abs(pinner2[ipar]-param1I[ipar])>pullCut[ipar]*TMath::Sqrt(TMath::Max(covar1I[index],pcovar2[index]))) isOK=kFALSE;
380 if (!isOK) return kFALSE;
388 AliXRDPROOFtoolkit toolkit;
389 chainOFFHLT= toolkit.MakeChainRandom("dumpHLTOFFLINE.list","offhlt",0,100);
390 chainOFFHLT0=toolkit.MakeChainRandom("dumpHLTOFFLINE.list","offhlt0",0,100);
391 chainHLTOFF=toolkit.MakeChainRandom("dumpHLTOFFLINE.list","hltoff",0,100);
392 chainHLTOFF0=toolkit.MakeChainRandom("dumpHLTOFFLINE.list","hltoff0",0,100);
399 // Draw difference between the HLT and offline tracks
401 TCut cut="sqrt(chi2)<10&&ncl21off>120";
402 TCut cutNoiseEvent = "abs(nHLT/nOFF-1)<0.2"; //mainly laser events
404 // 1. check the edge effect 1/pt resolution TPC only pull
406 chainOFFHLT->Draw("(track1.fIp.fP[4]-track2.fIp.fP[4])/sqrt(max(track1.fIp.fC[14],track2.fIp.fC[14])):sign(inner2.fP[4])*inner2.fP[0]/inner2.fX>>hisTPCEdge(50,-0.18,0.18,100,-6,6)",cut+"abs(track1.fP[4])<0.25","colz",200000);
408 hisTPCEdge->FitSlicesY();
409 hisTPCEdge_2->GetXaxis()->SetTitle("q*ly/lx");
410 hisTPCEdge_2->GetYaxis()->SetTitle("#Delta_{1/pt}/#sigma_{1/pt}");
411 hisTPCEdge_2->Draw();
413 // 2. check the edge effect 1/pt resolution combined
414 chainOFFHLT->Draw("(track1.fP[4]-track2.fP[4])/sqrt(max(track1.fC[14],track2.fC[14])):sign(inner2.fP[4])*inner2.fP[0]/inner2.fX>>hisCombEdge(50,-0.18,0.18,100,-6,6)",cut+"abs(track1.fP[4])<0.25","colz",200000);
416 hisCombEdge->FitSlicesY();
417 hisCombEdge_2->Draw();
419 // 3. Combined momentum resolution as function of the inverse moment
420 chainOFFHLT->Draw("(track1.fIp.fP[4]-track2.fIp.fP[4])/sqrt(max(track1.fIp.fC[14],track2.fIp.fC[14])):abs(track1.fP[4])>>hisTPCP4(20,-0.0,1,100,-6,6)",cut+"abs(track1.fP[4])<1","colz",200000);
422 hisTPCP4->FitSlicesY();
423 hisTPCP4_2->GetXaxis()->SetTitle("1/p_{t} (1/GeV))");
424 hisTPCP4_2->GetYaxis()->SetTitle("#Delta_{1/pt}/#sigma_{1/pt}");
427 // 4. Combined momentum resolution as function of the inverse moment
428 chainOFFHLT->Draw("(track1.fP[4]-track2.fP[4])/sqrt(max(track1.fC[14],track2.fC[14])):abs(track1.fP[4])>>hisCombP4(20,-0.0,1,100,-6,6)",cut+"abs(track1.fP[4])<1","colz",200000);
430 hisCombP4->FitSlicesY();
440 TCut cutEff = "abs(track.fIp.fP[4])<5&&abs(track.fIp.fP[1])<90";
441 TCut cutNoiseEvent = "abs(nHLT/nOFF-1)<0.2"; // HLT cluster finder more sensitive to the noise
445 chainOFFHLT0->Draw("counter==0:(nOFF+nHLT)/2.>>effOccuOFFHLT(20,0,8000)",cutNoiseEvent+cutEff+"abs(track.fP[4])<1&&ncl21>120","prof",50000);
446 chainHLTOFF0->Draw("counter==0:(nOFF+nHLT)/2.>>effOccuHLTOFF(20,0,8000)",cutNoiseEvent+cutEff+"abs(track.fP[4])<1&&ncl21>120","prof",50000);
448 chainOFFHLT0->Draw("counter==0:track.fTPCncls>>effNCLOFFHLT(40,0,160)",cutNoiseEvent+cutEff+"abs(track.fP[4])<1","prof",50000);
449 chainHLTOFF0->Draw("counter==0:track.fTPCncls>>effNCLHLTOFF(40,0,160)",cutNoiseEvent+cutEff+"abs(track.fP[4])<1","prof",50000);
451 effNCLOFFHLT->SetMarkerStyle(25);
452 effNCLHLTOFF->SetMarkerStyle(25);
453 effNCLOFFHLT->SetMarkerColor(2);
454 effNCLHLTOFF->SetMarkerColor(4);
455 effNCLOFFHLT->Draw();
456 effNCLHLTOFF->Draw("same");
460 chainHLTOFF0->Draw("counter==0:sign(track.fIp.fP[4])*track.fIp.fP[0]/track.fIp.fX>>profTPCEdge(50,-0.18,0.18)",cutNoiseEvent+cutEff+"abs(track.fP[4])<0.25","prof",50000);
462 chainOFFHLT0->Draw("counter==0:sign(track.fIp.fP[4])*track.fIp.fP[0]/track.fIp.fX>>profTPCEdge(50,-0.18,0.18)",cutNoiseEvent+cutEff+"abs(track.fP[4])<1","prof",50000);
464 chainOFFHLT0->Draw("track.fTPCncls:sign(track.fIp.fP[4])*track.fIp.fP[0]/track.fIp.fX>>profTPCEdge(50,-0.18,0.18)",cutNoiseEvent+cutEff+"abs(track.fP[4])<1","prof",50000);
470 This is shell script real example to submit jobs for the track comparison:
476 split offline.list --lines=50 list -d
477 for a in `ls list*`; do
480 mv ../$a compare.list
481 bsub -q proof -oo outcompare.log aliroot -b -q $ALICE_ROOT/PWG1/TPC/macroscompareTracks.C+
485 find `pwd`/ | grep .root > dumpHLTOFFLINE.list