]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/macros/AliHLTTPCTrackerEvaluation.C
33be8e84a3630010c14f7a293a2028d3189ab7b1
[u/mrichter/AliRoot.git] / HLT / TPCLib / macros / AliHLTTPCTrackerEvaluation.C
1 // $Id$
2 /*
3  * Modified version of $ALICE_ROOT/TPC/AliTPCComparison.C for evaluating the
4  * performance of the CA tracker. 
5  * 
6  * Usage:
7  * <pre>
8  *   aliroot AliHLTTPCTrackerEvaluation.C
9  * </pre>
10  *
11  * documentation to be filled in when the macro is finalized 
12  *
13  *
14  * @ingroup alihlt_tpc
15  */
16 #if defined(__CINT__) && !defined(__MAKECINT__)
17
18 //Int_t AliHLTTPCTrackerEvaluation(const Char_t *dir=".", const char* input="AliHLTESDs.root", Float_t ptLowerCut=0.1, Float_t ptUpperCut=10., Bool_t bDedxAndClus=kFALSE)
19 {
20   gSystem->AddIncludePath("-I$ROOTSYS/include -I$ALICE_ROOT/include -I$ALICE_ROOT -I$ALICE_ROOT/TPC -I$ALICE/geant3/TGeant3");
21   gROOT->LoadMacro("AliHLTTPCTrackerEvaluation.C++");
22  
23   AliHLTTPCTrackerEvaluation();
24   // the attempt to pass the arguments with a self-called macro hasn't worked so far
25   //AliHLTTPCTrackerEvaluation(dir, input, ptLowerCut, ptUpperCut, bDedxAndClus);
26  
27 }
28 #else
29
30 #include <AliLog.h>
31 #include <TMath.h>
32 #include <TError.h>
33 #include <Riostream.h>
34 #include <TH1F.h>
35 #include <TH2F.h>
36 #include <TF1.h>
37 #include <TTree.h>
38 #include <TParticle.h>
39 #include <TCanvas.h>
40 #include <TLegend.h>
41 #include <TLine.h>
42 #include <TText.h>
43 #include <TBenchmark.h>
44 #include <TStyle.h>
45 #include <TFile.h>
46 #include <TROOT.h>
47
48 #include "AliStack.h"
49 #include "AliHeader.h"
50 #include "AliTrackReference.h"
51 #include "AliRunLoader.h"
52 #include "AliRun.h"
53 #include "AliESDEvent.h"
54 #include "AliESDtrack.h"
55 #include "AliTPCtrack.h"
56
57 #include "AliSimDigits.h"
58 #include "AliTPC.h"
59 #include "AliTPCParamSR.h"
60 #include "AliTPCClustersArray.h"
61 #include "AliTPCClustersRow.h"
62 #include "AliTPCcluster.h"
63 #include "AliTPCLoader.h"
64 #include "TParticlePDG.h"
65 #include "TDatabasePDG.h"
66
67 #include "AliCDBManager.h"
68 #include "AliTPCcalibDB.h"
69
70 //_______________________________________________________________________________________
71
72
73 Int_t GoodTPCTracks(const Char_t *dir = ".");
74
75 extern AliRun     *gAlice;
76 extern TBenchmark *gBenchmark;
77 extern TROOT      *gROOT;
78
79 static Int_t allgood     = 0;
80 static Int_t allselected = 0;
81 static Int_t allfound    = 0;
82
83
84
85 Int_t AliHLTTPCTrackerEvaluation(const Char_t *dir=".", const char* input="AliHLTESDs.root", Float_t ptLowerCut=0.1, Float_t ptUpperCut=10., Bool_t bDedxAndClus=kFALSE){
86  
87    if(!input){
88        cerr << "please specify an input file" << endl;
89        return 1;
90    }
91
92    gBenchmark->Start("AliHLTTPCTrackerEvaluation");
93
94    ::Info("AliHLTTPCTrackerEvaluation.C","Calculating reconstruction efficiency...");
95
96    gSystem->SetIncludePath("-I$ROOTSYS/include -I$ALICE_ROOT/include -I$ALICE_ROOT -I$ALICE/geant3/TGeant3");
97    
98    // --------------- Efficiency histograms ------------------------
99
100    TH1F *hClus      = new TH1F("hClus","# clusters on reconstructed tracks",300,0,300);  
101   
102    TH1F *hGood      = new TH1F("hGood",     "P_{t} distribution of MC tracks (selected for efficiency calculation)", 30, 0, 6);
103    TH1F *hFake      = new TH1F("hFake",     "P_{t} distribution of fake tracks",                                     30, 0, 6);
104    TH1F *hFound     = new TH1F("hFound",    "P_{t} distribution of reconstructed tracks",                            30, 0, 6);
105    TH1F *hFoundMult = new TH1F("hFoundMult","P_{t} distribution of reconstructed tracks with clones",                30, 0, 6);
106    TH1F *hClone     = new TH1F("hClone",    "P_{t} distribution of clone tracks",                                    30, 0, 6);
107  
108    TH1F *hEff      = new TH1F("hEff",     "Reconstruction efficiency based on selected MC tracks", 30, 0, 6);
109    TH1F *hFakeEff  = new TH1F("hFakeEff", "Efficiency for fake tracks",                            30, 0, 6);
110    TH1F *hCloneEff = new TH1F("hCloneEff","Efficiency for clone tracks",                           30, 0, 6);
111  
112    hEff->SetLineWidth(2);
113    hEff->SetMaximum(1.4);
114    hEff->SetYTitle("efficiency"); 
115    hEff->GetYaxis()->CenterTitle();
116    hEff->SetXTitle("P_{t} (GeV/c)");
117  
118    hFakeEff->SetLineColor(kRed); 
119    hFakeEff->SetLineWidth(2);
120  
121    hCloneEff->SetLineColor(kBlue); 
122    hCloneEff->SetLineWidth(2);
123  
124    TH2F *hDedx = new TH2F("hDedx","dE/dx vs. momentum", 50,0.,2.,50,0.,400.);
125    hDedx->SetMarkerStyle(8);
126    hDedx->SetMarkerSize(0.4);
127    hDedx->SetXTitle("P (Gev/c)"); 
128    hDedx->SetYTitle("dE/dx (a.u.)");
129
130    TH1F *hnhit_ref = new TH1F("hnhit_ref","# clusters on reco tracks, used in fit performance",300,0,300);
131    TH1F *he = new TH1F("he","dE/dx for pions with 0.4<p<0.5 GeV/c",50,0.,100.);
132
133    // --------------- Resolution histograms ---------------------------
134    
135    TH2F *hPt     = new TH2F("hPt",     "", 30, 0, 6, 50,  -3,  3); 
136    TH2F *hPhi    = new TH2F("hPhi",    "", 30, 0, 6, 50, -16, 16); 
137    TH2F *hLambda = new TH2F("hLambda", "", 30, 0, 6, 50, -10, 10);
138    TH2F *hY      = new TH2F("hY",      "", 30, 0, 6, 30,  -5,  5); 
139    TH2F *hZ      = new TH2F("hZ",      "", 30, 0, 6, 30,  -5,  5); // fix the x axis, if this is z dependent 
140    
141    TH1F *hResPt     = new TH1F("hResPt",     "P_{t} resolution",  30, 0, 6);
142    TH1F *hResPhi    = new TH1F("hResPhi",    "#phi resolution",   30, 0, 6);    
143    TH1F *hResLambda = new TH1F("hResLambda", "#lambda resolution",30, 0, 6);
144    TH1F *hResY      = new TH1F("hResY",      "Y resolution",      30, 0, 6); 
145    //TH1F *hResZ      = new TH1F("hResZ",      "Z resolution",      30, 0, 6); // select appropriate x axis, KKK
146
147    hResPt->SetXTitle("P_{t} (GeV/c)");
148    hResPt->SetYTitle("#sigma_{(P_{t}-P_{MC})/P_{MC}} (%)");
149    hResPt->GetYaxis()->CenterTitle(true);
150   
151    hResPhi->SetXTitle("P_{t} (GeV/c)");
152    hResPhi->SetYTitle("#sigma_{(#phi_{rec}-#phi_{MC})/#phi_{MC}} (%)");
153    hResPhi->GetYaxis()->CenterTitle(true);
154
155    hResLambda->SetXTitle("P_{t} (GeV/c)");
156    hResLambda->SetYTitle("#sigma_{(#lambda_{rec}-#lambda_{MC})/#lambda_{MC}} (%)"); // KKK perhaps we should add the definition on the histo pad
157    hResLambda->GetYaxis()->CenterTitle(true);
158   
159    hResY->SetXTitle("P_{t} (GeV/c)");
160    hResY->SetYTitle("#sigma_{(Y_{rec}-Y_{MC})/Y_{MC}} (%)");
161    hResY->GetYaxis()->CenterTitle(true);
162    
163 //    hResZ->SetXTitle("Z (mm)");
164 //    hResZ->SetYTitle("#sigma_{(Z_{rec}-Z_{MC})/Z_{MC}} (%)");
165 //    hResZ->GetYaxis()->CenterTitle(true);
166
167    // KKK I leave the Z coordinate up to you. You can make the hResZ Z dependent.
168    
169          
170    TH1D *hProjPt[6], *hProjPhi[6], *hProjLambda[6], *hProjY[6], *hProjZ[6]; // I am not sure we need these histos to be pointers
171    Char_t name[15];  Char_t title[100];
172     
173    for(Int_t i=0; i<6; i++){
174        sprintf(name,"hProjPt%i",i+1);
175        sprintf(title,"(Pt_{MC}-Pt_{Rec})/Pt_{MC} @ Pt#in[%f, %f] GeV/c", i-0.5, i+0.5);
176        hProjPt[i] = new TH1D(name, title, 50, -3, -3); 
177        
178        sprintf(name,"hProjPhi%i",i+1);
179        sprintf(title,"(#phi_{MC}-#phi_{Rec})/#phi_{MC} @ #phi#in[%f, %f] GeV/c", i-0.5, i+0.5);
180        hProjPhi[i] = new TH1D(name, title, 50, -16, -16);        
181       
182        sprintf(name,"hProjLambda%i",i+1);
183        sprintf(title,"(#lambda_{MC}-#lambda_{Rec})/#lambda_{MC} @ #lambda#in[%f, %f] GeV/c", i-0.5, i+0.5);
184        hProjLambda[i] = new TH1D(name, title, 50, -16, -16);        
185        
186        sprintf(name,"hProjY%i",i+1);
187        sprintf(title,"(Y_{MC}-Y_{Rec})/Y_{MC} @ Y#in[%f, %f] GeV/c", i-0.5, i+0.5);
188        hProjY[i] = new TH1D(name, title, 50, -16, -16);   
189        
190        // here you add the hProjZ[] histograms    KKK 
191    }
192  
193    
194      
195    // --------------- Pull variable histograms ------------------------
196
197    TH1F *hpullPhi  = new TH1F("hpullPhi", "SinPhi pull", 30,-10.,10.); 
198    TH1F *hpullY    = new TH1F("hpullY",   "Y pull",      30,-10.,10.); 
199    TH1F *hpullZ    = new TH1F("hpullZ",   "Z pull",      30,-10.,10.); 
200    TH1F *hpullDzds = new TH1F("hpullDzds","Dzds pull",   30,-10.,10.); 
201    TH1F *hpullK    = new TH1F("hpullK",   "Kappa pull",  30,-10.,10.); 
202
203 //---------------------------------------------------------------------------------------
204
205    Char_t fname[100];
206    sprintf(fname,"%s/GoodTPCTracks.root",dir);
207
208    TFile *refFile = TFile::Open(fname,"old");
209    if(!refFile || !refFile->IsOpen()){
210       ::Info("AliHLTTPCTrackerEvaluation.C","Marking good tracks (will take a while)...");
211       if(GoodTPCTracks(dir)){
212          ::Error("AliHLTTPCTrackerEvaluation.C","Cannot generate the reference file!");
213          return 1;
214      }
215    }
216   
217    refFile = TFile::Open(fname,"old");
218    if(!refFile || !refFile->IsOpen()){
219       ::Error("AliHLTTPCTrackerEvaluation.C","Cannot open the reference file!");
220       return 2;
221    }   
222    
223    //------------ access the contents of the tree created by the function GoodTracks() -------------
224   
225    TTree *tpcTree = (TTree*)refFile->Get("tpcTree");
226    if(!tpcTree){
227       ::Error("AliHLTTPCTrackerEvaluation.C","Cannot get the reference tree!");
228       return 3;
229    }
230    
231    TBranch *branch = tpcTree->GetBranch("TPC");
232    if(!branch){
233       ::Error("AliHLTTPCTrackerEvaluation.C","Cannot get the TPC branch!");
234       return 4;
235    }
236   
237    TClonesArray dummy("AliTrackReference",1000), *refs = &dummy;
238    branch->SetAddress(&refs);
239
240    //------------ access the HLT output --------------------
241
242    sprintf(fname,"%s/%s", dir, input);
243    TFile *ef = TFile::Open(fname);
244    
245    if( !ef || !ef->IsOpen() ){
246       ::Error("AliHLTTPCTrackerEvaluation.C","Cannot open [%s]!",fname);
247       return 5;   
248    }
249    
250    AliESDEvent *event = new AliESDEvent();
251    TTree *esdTree = NULL;
252    TString tsinput = input;
253    
254    if(tsinput.CompareTo("AliESDs.root")==0){
255       esdTree = (TTree*)ef->Get("HLTesdTree");
256       if(!esdTree){
257          ::Error("AliHLTTPCTrackerEvaluation.C", "no HLTESD tree found");
258          return 6;
259       }
260    event->ReadFromTree(esdTree);
261    } else if(tsinput.CompareTo("AliHLTESDs.root")==0){
262       esdTree = (TTree*)ef->Get("esdTree");
263       if(!esdTree){
264          ::Error("AliHLTTPCTrackerEvaluation.C", "no ESD tree found");
265          return 7;
266       }
267    event->ReadFromTree(esdTree);
268    } else return 8;
269       
270
271    //---------- Loop over events -------------------
272
273    Int_t iEvent = 0;
274    while(esdTree->GetEvent(iEvent)){
275      
276       Int_t nEntries = event->GetNumberOfTracks();      
277       //cout << "********* Processing event number: " << iEvent << ", " << nEntries << " reconstructed tracks *******\n" << endl;
278
279       allfound += nEntries;
280
281       if(tpcTree->GetEvent(iEvent++)==0){
282          cerr << "No reconstructable tracks !\n";
283          continue;
284       }
285
286       Int_t ngood = refs->GetEntriesFast(); // access the track references
287       //cout << ngood << " good MC tracks" << endl;
288       allgood += ngood;
289
290       const Int_t MAX = 15000;
291   
292       Int_t track_notfound[MAX],                            itrack_notfound   = 0;
293       Int_t track_fake[MAX],                                itrack_fake       = 0;
294       Int_t track_multifound[MAX], track_multifound_n[MAX], itrack_multifound = 0;
295
296       for(Int_t i=0; i<nEntries; i++){
297           
298           hClus->Fill(event->GetTrack(i)->GetTPCNcls()); // filled but not displayed
299           //cout << "TPC label for track " << i << " = " << event->GetTrack(i)->GetTPCLabel() << ", # clusters " << event->GetTrack(i)->GetTPCNcls() << endl;
300       }
301       
302       Int_t i;
303       for(Int_t k=0; k<ngood; k++){ // read the MC information
304
305           AliTrackReference *ref = (AliTrackReference*)refs->UncheckedAt(k); 
306          
307           Int_t  label = ref->Label();
308           Int_t tlabel = -1;
309           Float_t ptMC = TMath::Sqrt(ref->Px()*ref->Px() + ref->Py()*ref->Py());
310           Float_t pMC  = TMath::Sqrt(ref->Px()*ref->Px() + ref->Py()*ref->Py()+ref->Pz()*ref->Pz());
311         
312           if (ptMC<1e-33 || ptMC<ptLowerCut || ptMC>ptUpperCut) continue; // first condition is for tracks not crossing padrow 0
313           allselected++;
314
315           hGood->Fill(ptMC);
316           
317           for(i=0; i<nEntries; i++){               
318               Int_t ttlabel = event->GetTrack(i)->GetTPCLabel();
319               if( label==TMath::Abs(ttlabel) && ttlabel<0 ){
320                  track_fake[itrack_fake++] = label;
321                  hFake->Fill(ptMC);
322               }       
323           }
324         
325           AliESDtrack *esdtrack = 0;
326           for(i=0; i<nEntries; i++){            
327               esdtrack = event->GetTrack(i);
328               tlabel   = esdtrack->GetTPCLabel();
329               if(label==tlabel) break;
330           }
331         
332           if(i==nEntries){
333              track_notfound[itrack_notfound++] = label;
334              //cout << "MC track " << label << " not reconstructed" << endl;
335              continue;
336           }
337       
338           Int_t micount = 0;
339           Int_t mi;
340           AliESDtrack *mitrack;
341
342           for(mi=0; mi<nEntries; mi++){
343               mitrack = event->GetTrack(mi);          
344               if(label==mitrack->GetTPCLabel()) micount++;
345           }
346         
347           if(micount>1){
348              track_multifound[itrack_multifound]   = label;
349              track_multifound_n[itrack_multifound] = micount;
350              itrack_multifound++;
351              hClone->Fill(ptMC,micount-1);          
352           }
353         
354         //if((mitrack->GetStatus()&AliESDtrack::kTPCrefit)==0) continue;
355         //if((mitrack->GetStatus()&AliESDtrack::kTPCin)==0)    continue;
356        
357         if(label==tlabel){
358            hFound->Fill(ptMC);
359            //if( micount<1 ) cout<<"ERROR!!!!"<<endl;
360            hFoundMult->Fill(ptMC,micount);
361         }       
362         
363         AliExternalTrackParam tpctrack =*(esdtrack->GetInnerParam());
364
365         if( TMath::Abs(tpctrack.GetSigned1Pt()) <1.e-8 ) continue;
366         
367         Double_t mcxyz[3]   = { ref->X(), ref->Y(), ref->Z() };
368         Double_t mclocal[3] = { ref->X(), ref->Y(), ref->Z() };
369         
370         if(1){
371           Double_t c = TMath::Cos(tpctrack.GetAlpha());
372           Double_t s = TMath::Sin(tpctrack.GetAlpha());
373           Double_t x = mclocal[0];
374           mclocal[0] = x*c + mclocal[1]*s;
375           mclocal[1] =-x*s + mclocal[1]*c;
376         }
377         
378         if(0){    
379           Double_t local[3] = { tpctrack.GetX(),tpctrack.GetY(),tpctrack.GetZ() };
380 //        cout << "label: "      << label << endl;
381 //        cout << "Z diff = "    << local[2] - mclocal[2] << endl;
382 //        cout << "orig rec: "   << local[0]<<" "<<local[1]<<" "<<local[2] <<" "<<TMath::Sqrt(local[0]*local[0]+local[1]*local[1])<<endl;
383 //        cout << "rotated mc: " << mclocal[0]<<" "<<mclocal[1]<<" "<<mclocal[2] <<" "<<TMath::Sqrt(mclocal[0]*mclocal[0]+mclocal[1]*mclocal[1])<<endl;
384 //        cout << "orig mc: "    << mcxyz[0]<<" "<<mcxyz[1]<<" "<<mcxyz[2]<<endl;
385 //        cout << "alpha = "     << tpctrack.GetAlpha()/TMath::Pi()*180.<<" "<<ref->Alpha()/TMath::Pi()*180.<<endl;
386         }
387
388         //cout << "X = " << mclocal[0] << " / " << tpctrack.GetX() << endl;     
389         tpctrack.AliExternalTrackParam::PropagateTo(mclocal[0],5.);
390        
391         Double_t xyz[3], pxpypz[3]; 
392
393         tpctrack.GetXYZ(xyz);       // GetInnerXYZ
394         tpctrack.GetPxPyPz(pxpypz); // GetInnerPxPyPz
395         
396         Double_t local[3] = { tpctrack.GetX(),tpctrack.GetY(),tpctrack.GetZ() };
397         Float_t phiRec = TMath::ATan2(pxpypz[1],pxpypz[0]);
398         
399         if(phiRec <= TMath::Pi()) phiRec += 2*TMath::Pi();
400         if(phiRec >= TMath::Pi()) phiRec -= 2*TMath::Pi();
401         
402         Double_t ptRec = TMath::Sqrt(pxpypz[0]*pxpypz[0]+pxpypz[1]*pxpypz[1]);
403         Double_t pRec  = TMath::Sqrt(pxpypz[0]*pxpypz[0]+pxpypz[1]*pxpypz[1]+pxpypz[2]*pxpypz[2]);
404         
405         Float_t  lambdaRec = TMath::ATan2(pxpypz[2],ptRec); 
406         Float_t pt_1 = 1./ptRec;
407         //Float_t pts_1 = tpctrack->GetSigned1Pt();
408         //Float_t ptMCs_1 = ref->/ptMC;
409
410         
411
412         Int_t pdg = (Int_t)ref->GetLength();  // particle PDG
413         const Double_t kCLight = 0.000299792458;  
414         //Double_t Bz = 5.;
415         Double_t q  = 0.;
416         
417         if( TMath::Abs(pdg)<10000 ){
418            TParticlePDG *ppdg = TDatabasePDG::Instance()->GetParticle(pdg);
419            if( ppdg ) q = ppdg->Charge()/3.;
420         }
421         
422         Double_t kappaMC = q/ptMC; // /Bz/kCLight;
423         hnhit_ref->Fill(esdtrack->GetTPCNcls());    
424  
425         hPt->Fill(ptMC, (ptRec - ptMC)/(ptMC)*100.);           
426         
427         Float_t phiMC = TMath::ATan2(ref->Py(),ref->Px());
428         hPhi->Fill(ptMC, (phiRec - phiMC)/phiMC*1000.);
429
430         Float_t lambdaMC = TMath::ATan2(ref->Pz(),ptMC);
431         hLambda->Fill(ptMC, (lambdaRec - lambdaMC)/lambdaMC*1000.);    
432         
433         hY->Fill(ptMC, (local[1]-mclocal[1])*10.);
434         /*if(mclocal[2]>0 )*/ //hZ->Fill( (local[2]-mclocal[2] ) *10.); // Please check hY and hZ! KKK
435         
436         if( tpctrack.GetSigmaY2()>0   && finite(tpctrack.GetSigmaY2())   )  hpullY   ->Fill( (local[1]-mclocal[1])/TMath::Sqrt(TMath::Abs(tpctrack.GetSigmaY2()))  );
437         if( tpctrack.GetSigmaZ2()>0   && finite(tpctrack.GetSigmaZ2())   )  hpullZ   ->Fill( (local[2]-mclocal[2])/TMath::Sqrt(TMath::Abs(tpctrack.GetSigmaZ2()))  );
438         if( tpctrack.GetSigmaSnp2()>0 && finite(tpctrack.GetSigmaSnp2()) )  hpullPhi ->Fill( (phiRec-phiMC)/TMath::Sqrt(TMath::Abs(tpctrack.GetSigmaSnp2()))       );
439         if( tpctrack.GetSigmaTgl2()>0 && finite(tpctrack.GetSigmaTgl2()) )  hpullDzds->Fill( (lambdaRec-lambdaMC)/TMath::Sqrt(TMath::Abs(tpctrack.GetSigmaTgl2())) );
440         
441         if( tpctrack.GetSigma1Pt2()>0 && finite(tpctrack.GetSigma1Pt2()) )
442         if( q!=0 ) hpullK->Fill((tpctrack.GetSigned1Pt()-kappaMC)/TMath::Sqrt(TMath::Abs(tpctrack.GetSigma1Pt2())));    
443         
444         Float_t dedx = esdtrack->GetTPCsignal();        
445         hDedx->Fill(pRec,dedx,1.);
446         
447         if(TMath::Abs(pdg)==211) // pions
448            if(pRec>0.4 && pRec<0.5){
449               he->Fill(dedx,1.);
450            }
451       } // end of loop over "good" tracks
452             
453       /*
454       cout<<"\nList of Not found tracks :\n";
455       for ( i = 0; i< itrack_notfound; i++){
456         cout<<track_notfound[i]<<"\t";
457         if ((i%5)==4) cout<<"\n";
458       }
459       cout<<"\nList of fake  tracks :\n";
460       for ( i = 0; i< itrack_fake; i++){
461         cout<<track_fake[i]<<"\t";
462         if ((i%5)==4) cout<<"\n";
463       }
464       cout<<"\nList of multiple found tracks :\n";
465       for ( i=0; i<itrack_multifound; i++) {
466           cout<<"id.   "<<track_multifound[i]
467               <<"     found - "<<track_multifound_n[i]<<"times\n";
468       }
469
470       cout<<"Number of found tracks ="<<nEntries<<endl;
471       cout<<"Number of \"good\" tracks ="<<ngood<<endl;
472       */
473       
474   refs->Clear();
475   } // end of the loop over events
476
477    delete event;
478    delete esdTree;
479    ef->Close();
480
481    delete tpcTree;
482    refFile->Close();
483
484    Stat_t nGoodMC  = hGood->GetEntries();
485    Stat_t nFakes   = hFake->GetEntries();
486    Stat_t nClones  = hClone->GetEntries();
487    Stat_t nRec     = hFound->GetEntries();
488    Stat_t nRecMult = hFoundMult->GetEntries();
489    
490    
491     if(nGoodMC!=0)         ::Info("\n\nAliHLTTPCTrackerEvaluation","Integral efficiency in (%) is about : %f\n", nRec/nGoodMC*100.); 
492     if(nRecMult+nFakes!=0) ::Info("AliHLTTPCTrackerEvaluation","Integral fake rate in (%) is about  : %f\n", nFakes/(nRecMult+nFakes)*100.);
493     if(nRecMult+nFakes!=0) ::Info("AliHLTTPCTrackerEvaluation","Integral clone rate in (%) is about : %f\n", nClones/(nRecMult+nFakes)*100.);
494     
495     ::Info("AliHLTTPCTrackerEvaluation", "Total number of selected MC tracks                    : %d\n", allgood);
496     ::Info("AliHLTTPCTrackerEvaluation", "Total number of selected MC tracks with momentum cuts : %d\n", allselected);
497     ::Info("AliHLTTPCTrackerEvaluation", "Total number of reconstructed tracks                  : %d\n", allfound);
498
499
500    // ---------- Plotting the histograms ----------------------------------------------------------------------------
501    
502    hFound    ->Sumw2(); 
503    hFoundMult->Sumw2(); 
504    hGood     ->Sumw2(); 
505    hFake     ->Sumw2(); 
506    hClone    ->Sumw2();
507   
508    hEff     ->Divide(hFound,hGood,     1,1.,"b");
509    hFakeEff ->Divide(hFake, hGood,     1,1.,"b");
510    hCloneEff->Divide(hClone,hFoundMult,1,1.,"b"); 
511    // KKK are you sure this is the correct definition? When plotted, it looks like we have 70% clones in the lower momenta...
512    // perhaps fakes and clones should be displayed in another histogram??
513
514    gROOT->SetStyle("Plain");
515    gStyle->SetOptStat(0); //gStyle->SetOptStat(111110);
516    gStyle->SetOptFit(0);  //gStyle->SetOptFit(1);
517    gStyle->SetPalette(1);
518    
519    //--------------- canvas 0 for EFFICIENCY -------------------
520    
521    TCanvas *c0 = new TCanvas("c0","reconstruction efficiency",500,450);
522    
523    c0->cd();
524    hEff     ->Draw();
525    hCloneEff->Draw("histsame");
526    hFakeEff ->Draw("histsame");
527    
528    TLegend *leg = new TLegend(0.3,0.5,0.85,0.8);
529    leg->SetFillColor(10);
530    leg->SetLineColor(10);
531    leg->AddEntry(hEff,      "reconstruction eff.", "l");
532    leg->AddEntry(hCloneEff, "clone contribution", "l");
533    leg->AddEntry(hFakeEff,  "fake contribution",  "l");
534    leg->Draw("same");
535       
536    TLine *line1 = new TLine(0,1,6,1); 
537    line1->SetLineStyle(4);
538    line1->Draw("same");
539    
540    Float_t fakeData  = nFakes/(nRecMult+nFakes)*100.;
541    Float_t cloneData = nClones/(nRecMult+nFakes)*100.;
542    Char_t  fakeBuf[100];
543    Char_t  cloneBuf[100];
544
545    sprintf(fakeBuf,"%d", (Int_t)fakeData);
546    TString fakeStr = fakeBuf;
547    fakeStr.Append(" %");
548    
549    sprintf(cloneBuf,"%d", (Int_t)cloneData);
550    TString cloneStr = cloneBuf;
551    cloneStr.Append(" %");
552      
553    TText *text = new TText(1.4,0.1,fakeStr.Data());
554    text->SetTextSize(0.05);
555    text->SetTextColor(kRed);
556    text->Draw();
557    text = new TText(0.6,0.3,cloneStr.Data());
558    text->SetTextSize(0.05);
559    text->SetTextColor(kBlue);
560    text->Draw();
561    
562    
563    //--------------- canvas 1 for RESOLUTIONS ----------------
564
565    
566    TCanvas *c1 = new TCanvas("c1","resolutions",1100,900); // please add the Y and Z projections
567      
568    TF1 *fGauss = new TF1("gauss","gaus");   
569    for(Int_t i=0; i<6; i++){              
570        Float_t pMin = i - 0.5;
571        Float_t pMax = i + 0.5;
572        Int_t binx1 = hPt->GetXaxis()->FindBin(pMin);
573        Int_t binx2 = hPt->GetXaxis()->FindBin(pMax);
574        if(i>0) binx1++;
575             
576        *hProjPt[i]     = *(hPt    ->ProjectionY("", binx1, binx2));  
577        *hProjPhi[i]    = *(hPhi   ->ProjectionY("", binx1, binx2));  
578        *hProjLambda[i] = *(hLambda->ProjectionY("", binx1, binx2));  
579        *hProjY[i]      = *(hY     ->ProjectionY("", binx1, binx2));  
580 //        *hProjZ[i]      = *(hZ     ->ProjectionY("", binx1, binx2));  
581
582        if(hProjPt[i]->GetEntries()>30) hProjPt[i]->Fit("gauss","Q"); 
583        hResPt->Fill(i+0.5, fGauss->GetParameter(2));fGauss->GetParError(2);
584        fGauss->SetParameter(2,0); fGauss->SetParError(2,0);
585        //KKK I am resetting only the sigma and its error, perhaps we should do this with all the fit parameters ???
586        
587        if(hProjPhi[i]->GetEntries()>30) hProjPhi[i]->Fit("gauss","Q"); 
588        hResPhi->Fill(i+0.5, fGauss->GetParameter(2)); fGauss->GetParError(2);
589        fGauss->SetParameter(2,0); fGauss->SetParError(2,0);
590       
591        if(hProjLambda[i]->GetEntries()>30) hProjLambda[i]->Fit("gauss","Q"); 
592        hResLambda->Fill(i+0.5, fGauss->GetParameter(2)); fGauss->GetParError(2);
593        fGauss->SetParameter(2,0);
594        
595        if(hProjY[i]->GetEntries()>30) hProjY[i]->Fit("gauss","Q"); 
596        hResY->Fill(i+0.5, fGauss->GetParameter(2)); fGauss->GetParError(2);
597        fGauss->SetParameter(2,0); fGauss->SetParError(2,0);
598        
599 //        if(hProjZ[i]->GetEntries()>30) hProjZ[i]->Fit("gauss","Q"); 
600 //        hResZ->Fill(i+0.5, fGauss->GetParameter(2)); fGaus->GetParError(2);
601 //        fGauss->SetParameter(2,0); KKK
602        
603    }   
604   
605    c1->Clear(); c1->Divide(3,2);  
606    
607    c1->cd(1);
608    hResPt->Draw(); // KKK I haven't filled the errors for the sigma, perhaps a TGraph would make them easier to plot
609   
610    c1->cd(2);
611    hResPhi->Draw();
612    
613    c1->cd(3);
614    hResLambda->Draw();
615    
616    c1->cd(4);
617    hResY->Draw();
618    
619 //    c1->cd(4);
620 //    hResZ->Draw(); // KKK
621
622 // pad 6 stays empty
623   
624
625    //----------------- optional canvases 2 and 3 for dE/dx and clusters ----------------
626       
627    if(bDedxAndClus){     
628       TCanvas *c2 = new TCanvas("c2","dE/dx",500,450);
629       c2->cd();
630       hDedx->Draw();  
631         
632       TCanvas *c3 = new TCanvas("c","clusters",500,450);
633       c3->cd();   
634       hClus->Draw();
635       hnhit_ref->SetLineColor(kRed);
636       hnhit_ref->Draw("same");
637    }
638    
639    
640    //----------------- canvas 3 for PULL VARIABLES --------------------
641
642    TCanvas *c4 = new TCanvas("c4","pull variables",1100,900);
643    c4->Divide(3,2);
644    
645    c4->cd(1);
646    hpullY->Draw();
647    hpullY->Fit("gaus","Q");
648    
649    c4->cd(2);
650    hpullZ->Draw();
651    hpullZ->Fit("gaus","Q");
652    
653    c4->cd(3);
654    hpullPhi->Draw();
655    hpullPhi->Fit("gaus","Q");
656
657    c4->cd(4);
658    hpullDzds->Draw();
659    hpullDzds->Fit("gaus","Q");
660    
661    c4->cd(5);
662    hpullK->Draw();
663    hpullK->Fit("gaus","Q");
664
665
666
667 //-------------------- OUTPUT FILE ---------------------------------------- 
668    
669    //TFile fc("CAtrackerEvaluation.root","RECREATE");
670    //c1->Write();
671    //c2->Write();
672    //c3->Write();
673    //fc.Close(); // KKK commented out temporarily
674    
675    gBenchmark->Stop("AliHLTTPCTrackerEvaluation");
676    gBenchmark->Show("AliHLTTPCTrackerEvaluation");
677
678    return 0;
679 }
680
681
682 //============================================================================
683
684 Int_t GoodTPCTracks(const Char_t *dir){
685
686   Char_t fname[100];
687   sprintf(fname,"%s/galice.root",dir);
688
689   AliRunLoader *runLoader = AliRunLoader::Open(fname,"COMPARISON");
690   if (!runLoader) {
691      ::Error("GoodTPCTracks","Cannot start session!");
692      return 1;
693   }
694   
695   // load MC information
696   
697   runLoader->LoadgAlice();
698   runLoader->LoadHeader();
699   runLoader->LoadKinematics();
700   runLoader->LoadTrackRefs();
701
702   AliTPCLoader *tpcLoader = (AliTPCLoader*)runLoader->GetLoader("TPCLoader");
703   if (tpcLoader == 0x0) {
704      ::Error("GoodTPCTracks","Cannot find TPCLoader!");
705      delete runLoader;
706      return 2;
707   }
708      
709   AliTPC *TPC = (AliTPC*)runLoader->GetAliRun()->GetDetector("TPC");
710   Int_t tpcVersion = TPC->IsVersion(); 
711   
712   //cout << "TPC version "<< tpcVersion << " has been found!\n";
713    
714   if      (tpcVersion==1) tpcLoader->LoadRecPoints();
715   else if (tpcVersion==2) tpcLoader->LoadDigits();
716   else {
717      ::Error("GoodTPCTracks","Wrong TPC version!");
718      delete runLoader;
719      return 3;
720   } 
721
722   AliCDBManager *manager = AliCDBManager::Instance();
723   manager->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
724   manager->SetRun(0);
725   
726   // loading the TPC parameters
727   AliTPCParamSR *digp = (AliTPCParamSR*)(AliTPCcalibDB::Instance()->GetParameters());
728   if (!digp) { 
729     ::Error("AliHLTTPCTrackerEvaluation.C","TPC parameters have not been found!");
730     delete runLoader;
731     return 4; 
732   }
733
734   Int_t nrow_up     = digp->GetNRowUp();                           //get the number of pad rows in up sector
735   Int_t nrows       = digp->GetNRowLow()+nrow_up;                  //get the number of pad rows in low sector and add 
736   Int_t zeroSup     = digp->GetZeroSup();
737   Int_t gap         = Int_t(0.125*nrows), shift = Int_t(0.5*gap);
738   Int_t good_number = Int_t(0.4*nrows);                            // will be used for selecting tracks with hits in 40% of the rows
739
740   Int_t nEvents = runLoader->GetNumberOfEvents();
741   ::Info("GoodTPCTracks","Number of events : %d\n", nEvents);  
742
743   sprintf(fname,"%s/GoodTPCTracks.root",dir);
744   TFile *file = TFile::Open(fname,"recreate");
745
746   TClonesArray dummy("AliTrackReference",1000), *refs = &dummy;
747   TTree tpcTree("tpcTree","Tree with information about the reconstructable TPC tracks");
748   tpcTree.Branch("TPC",&refs);
749
750   
751   
752   //-------------- Loop over generated events ------------------------------
753   
754   for(Int_t iEvent=0; iEvent<nEvents; iEvent++){
755
756       Int_t nt = 0;
757       refs->Clear();
758
759       Int_t i;
760
761       runLoader->GetEvent(iEvent);  
762       file->cd();
763
764       Int_t nParticles = runLoader->GetHeader()->GetNtrack();
765       //cout << "Event " << iEvent << ", Number of particles: " << nParticles << endl;
766
767       // ------- Set the selection criteria for the MC sample that will be used for the efficiency -------
768       
769       Int_t *good = new Int_t[nParticles]; for(i=0; i<nParticles; i++) good[i] = 0;
770       
771       switch (tpcVersion){
772       case 1: // not used any more
773          {
774            AliTPCClustersArray *pca = new AliTPCClustersArray, &ca=*pca;
775            ca.Setup(digp);
776            ca.SetClusterType("AliTPCcluster");
777            ca.ConnectTree(tpcLoader->TreeR());
778            Int_t nrows=Int_t(ca.GetTree()->GetEntries());
779            for (Int_t n=0; n<nrows; n++) {
780              AliSegmentID *s=ca.LoadEntry(n);
781              Int_t sec,row;
782              digp->AdjustSectorRow(s->GetID(),sec,row);
783              AliTPCClustersRow &clrow = *ca.GetRow(sec,row);
784              Int_t ncl=clrow.GetArray()->GetEntriesFast();
785              while (ncl--) {
786                  AliTPCcluster *c=(AliTPCcluster*)clrow[ncl];
787                  Int_t label=c->GetLabel(0);
788                  if (label<0) continue; //noise cluster
789                  label=TMath::Abs(label);
790
791                  if (sec>=digp->GetNInnerSector())
792                     if (row==nrow_up-1) good[label]|=0x4000;
793                  if (sec>=digp->GetNInnerSector())
794                     if (row==nrow_up-1-gap) good[label]|=0x1000;
795
796                  if (sec>=digp->GetNInnerSector())
797                     if (row==nrow_up-1-shift) good[label]|=0x2000;
798                  if (sec>=digp->GetNInnerSector())
799                     if (row==nrow_up-1-gap-shift) good[label]|=0x800;
800
801                  good[label]++;
802              }
803              ca.ClearRow(sec,row);
804            }
805            delete pca;
806            }
807          break;
808      
809       case 2:
810          {
811            TTree *TD = tpcLoader->TreeD(); // get the digits tree
812        
813            AliSimDigits da, *digits = &da;
814            TD->GetBranch("Segment")->SetAddress(&digits);
815
816            Int_t *count = new Int_t[nParticles];
817            Int_t i;
818            for (i=0; i<nParticles; i++) count[i] = 0;
819
820            Int_t sectors_by_rows = (Int_t)TD->GetEntries();
821            
822            for(i=0; i<sectors_by_rows; i++){
823
824              if (!TD->GetEvent(i)) continue;
825              Int_t sec,row;
826              
827              digp->AdjustSectorRow(digits->GetID(),sec,row);
828              if(digits->First()){
829                do { 
830                  Int_t it    = digits->CurrentRow();
831                  Int_t ip    = digits->CurrentColumn();          
832                  Short_t dig = digits->GetDigit(it,ip);
833                  Int_t idx0  = digits->GetTrackID(it,ip,0); 
834                  Int_t idx1  = digits->GetTrackID(it,ip,1);
835                  Int_t idx2  = digits->GetTrackID(it,ip,2);
836                  if(idx0>=0 && dig>=zeroSup && idx0<nParticles) count[idx0]+=1;
837                  if(idx1>=0 && dig>=zeroSup && idx1<nParticles) count[idx1]+=1;
838                  if(idx2>=0 && dig>=zeroSup && idx2<nParticles) count[idx2]+=1;
839                } while (digits->Next());
840              }
841             
842              for(Int_t j=0; j<nParticles; j++){
843                 
844                  if(count[j]>1){
845                     if(sec>=digp->GetNInnerSector())
846                     if(row==nrow_up-1)               good[j]|=0x4000;
847                     if(sec>=digp->GetNInnerSector())
848                     if(row==nrow_up-1-gap)           good[j]|=0x1000;
849
850                     if(sec>=digp->GetNInnerSector())
851                     if(row==nrow_up-1-shift)         good[j]|=0x2000;
852                     if(sec>=digp->GetNInnerSector())
853                     if(row==nrow_up-1-gap-shift)     good[j]|=0x800;
854
855                     good[j]++;
856                  }
857                  count[j] = 0;
858              } // end of loop over particles
859            } // end of loop over sectors_by_rows
860            delete [] count;
861          } // end of case 2
862          break;
863       } // end of switch
864
865
866
867
868     // ---------------- Select sample of MC particles that will be used for forming the efficiency ------------------
869    
870     AliStack *stack = runLoader->Stack();
871
872     for(i=0; i<nParticles; i++){ // loop over stack
873
874         if ((good[i]&0x5000) != 0x5000)//SG!!!
875         if ((good[i]&0x2800) != 0x2800)     continue;
876         if ((good[i]&0x7FF ) < good_number) continue;
877         // N TPC rows with digits >= 64 => common checks of cluster finder & tracker
878         // There are digits in rows (159&&139) || (149&&129)
879
880
881         TParticle *part = (TParticle*)stack->Particle(i);
882         if(part == 0x0){
883            cerr << "Cannot get particle "<< i << endl;
884            continue;
885         }
886        
887         if(part->Pt()<0.100) continue;                        // skip particles with pt below 0.1 GeV/c
888         if(TMath::Abs(part->Pz()/part->Pt())>0.999) continue; // reject tracks outside the TPC acceptance, below 45 degrees 
889
890         Double_t vx = part->Vx();
891         Double_t vy = part->Vy();
892         Double_t vz = part->Vz();
893         //if (TMath::Sqrt(vx*vx+vy*vy)>3.5) continue; // vertex cuts
894         //if (TMath::Abs(vz) > 50.) continue;
895
896         AliTrackReference *ref = new((*refs)[nt])AliTrackReference();
897
898         ref->SetLabel(i);
899         Int_t pdg = part->GetPdgCode();
900         ref->SetLength(pdg);  //This will the particle's PDG !
901         ref->SetMomentum(0.,0.,0.);  
902         ref->SetPosition(0.,0.,0.);
903
904         nt++;
905     } // end of loop over stack
906
907     //----------- Check whether there is also information at the entrance of the TPC
908     
909     TTree   *TR     = runLoader->TreeTR();
910     TBranch *branch = TR->GetBranch("TrackReferences");
911     if(branch==0){
912        ::Error("GoodTPCTracks","No track references!");
913        delete runLoader;
914        return 5;
915     }
916     
917     TClonesArray tpcdummy("AliTrackReference",1000), *tpcRefs = &tpcdummy;
918     branch->SetAddress(&tpcRefs);
919
920     for(Int_t r=0; r<(Int_t)TR->GetEntries(); r++){ 
921
922         //cerr<<r<<' '<<(Int_t)TR->GetEntries()<<'\r';
923         TR->GetEvent(r);
924
925         if(!tpcRefs->GetEntriesFast()) continue;
926         
927         AliTrackReference *tpcRef = 0x0;                
928         for(Int_t iref=0; iref<tpcRefs->GetEntriesFast(); ++iref){
929
930             tpcRef = (AliTrackReference*)tpcRefs->UncheckedAt(iref);
931             if(tpcRef->DetectorId() == AliTrackReference::kTPC) break;
932             tpcRef = 0x0;
933         }
934
935         if(!tpcRef) continue;
936
937         Int_t j;
938         AliTrackReference *ref = 0;
939         
940         for(j=0; j<nt; j++){
941
942           ref = (AliTrackReference*)refs->UncheckedAt(j);
943           if(ref->Label()==tpcRef->Label()) break;
944           ref = 0;
945         }  
946         if(ref==0) continue;
947         
948         ref->SetMomentum(tpcRef->Px(),tpcRef->Py(),tpcRef->Pz());
949         ref->SetPosition(tpcRef->X(), tpcRef->Y(), tpcRef->Z());
950
951         tpcRefs->Clear();
952     }
953
954     tpcTree.Fill();
955
956     delete [] good;
957   } //---------- end of the loop over generated events
958   
959   tpcTree.Write();
960   file->Close();
961
962   delete runLoader;
963   return 0;
964 }
965 #endif