2 //---------------------------------------------------------------------------------
3 // The example of usage of AliKFParticle & AliKFVertex classes for V0 analysis
5 // @author S.Gorbunov, I.Kisel
9 // The AliKFParticleTest macro contains a toy V0 finder for ESD tracks.
10 // At the first step, event primary vertex is reconstructed.
11 // At the second step, ideal PID hypothesis are assigned to all the particles.
12 // At the third step, V0 candidates are constructed for each pair
13 // of positive and negative particles.
14 // V0 candidate considered as good when it passes Chi^2 cut and
15 // it is placed >= 3 Sigma away from the primary vertex.
16 // Invariant mass distribution for all good V0 candidates is plotted.
18 // -= Copyright © ALICE HLT Group =-
19 //_________________________________________________________________________________
23 #if !defined( __CINT__) || defined(__MAKECINT__)
25 //gSystem->AddIncludePath("-I\"$ALICE_ROOT/include\"");
27 #include <Riostream.h>
33 #include <TDatabasePDG.h>
34 #include <TParticle.h>
38 #include "AliESDEvent.h"
39 #include "AliTracker.h"
40 #include "AliKFParticle.h"
41 #include "AliKFVertex.h"
48 TH1D *histoMass[3]={0,0,0};
49 Int_t histoPDG [4]= {22,310,3122,421};
50 char* histoName[4]= {"#gamma","K^{0}_{s}","#Lambda","D^{0}"};
51 TLatex *histoText[4]={0,0,0,0};
55 //* Draw the invariant mass histogram
59 for( Int_t i=1; i<3; i++ ) histoMass[i]->Draw("same");
60 for( Int_t i=0; i<4; i++ ){
61 Double_t mass = TDatabasePDG::Instance()->GetParticle(histoPDG[i])->Mass();
62 Int_t bin = histoMass[2]->FindBin(mass) -5;
65 for( Int_t j=bin; j<bin+10; j++ )
66 if( max<histoMass[2]->GetBinContent(j) ) max = histoMass[2]->GetBinContent(j);
67 histoText[i]->SetY(max);
68 histoText[i]->SetX(mass+.05);
69 if(max>0) histoText[i]->Draw();
71 if( canvas ) canvas->Update();
76 //* (Re)create histograms and fill them from temporary file
78 TDirectory *curr = gDirectory;
79 canvas = new TCanvas();
80 histoMass[0] = new TH1D("massAll","AliKFParticle test", 500,0,3);
81 histoMass[0]->SetXTitle("V^{0} invariant mass [GeV]");
82 histoMass[1] = new TH1D("massMulti","V^{+-} contributions", 500,0,3);
83 histoMass[2] = new TH1D("massV0","V^{0} signal", 500,0,3);
84 histoMass[0]->SetLineColor(8);
85 histoMass[0]->SetFillColor(8);
86 histoMass[1]->SetLineColor(kMagenta);
87 histoMass[1]->SetFillColor(kMagenta);
88 histoMass[2]->SetLineColor(kBlue);
89 histoMass[2]->SetFillColor(kBlue);
90 for( Int_t i=0; i<4; i++ ){
91 histoText[i] = new TLatex(0,0,histoName[i]);
92 histoText[i]->SetTextColor(kBlue);
94 TFile* file = new TFile("AliKFParticleTest.root", "READ" );
95 if( !old_file && file ){
97 for( Int_t i=0; i<3; i++ ){
98 TObject *old = file->FindObjectAny(histoMass[i]->GetName());
99 if( old && histoMass[i] ) histoMass[i]->Add( (TH1D*) old);
109 //* End of gAlice -> store all histos in temporary file, clean memory
111 TDirectory *curr = gDirectory;
112 TFile* file = new TFile("AliKFParticleTest.root", "RECREATE" );
115 for( Int_t i=0; i<3; i++ ) histoMass[i]->Write();
117 for( Int_t i=0; i<3; i++ ) delete histoMass[i];
118 for( Int_t i=0; i<4; i++ ) delete histoText[i];
127 AliKFParticle fParticle; //* assigned KFParticle
128 Bool_t fPrimUsedFlag; //* flag shows that the particle was used for primary vertex fit
129 Bool_t fOK; //* is the track good enough
130 Int_t mcPDG; //* Monte Carlo PDG code
131 Int_t mcMotherID; //* Monte Carlo ID of its mother
134 void RunV0( AliESDEvent *event )
138 static Int_t iEvent = 0;
139 cout<<"Event "<<iEvent++<<endl;
141 if( !gAlice ) return;
142 AliRunLoader *rl = AliRunLoader::Instance();
144 AliStack *stack = rl->Stack();
147 Int_t nESDTracks=event->GetNumberOfTracks();
148 if( nESDTracks>1000 ) nESDTracks=1000;
151 TESDTrackInfo ESDTrackInfo[1000]; //* parallel to ESD tracks
153 //* Fill ESDTrackInfo array
155 for (Int_t iTr=0; iTr<nESDTracks; iTr++)
157 TESDTrackInfo &info = ESDTrackInfo[iTr];
159 info.fPrimUsedFlag = 0;
161 info.mcMotherID = -1;
163 //* track quality check
165 AliESDtrack *pTrack = event->GetTrack(iTr);
166 if( !pTrack ) continue;
167 if (pTrack->GetKinkIndex(0)>0) continue;
168 if ( !( pTrack->GetStatus()&AliESDtrack::kITSrefit ) ) continue;
170 if( pTrack->GetITSclusters(indi) <5 ) continue;
171 Int_t PDG = ( pTrack->GetSigned1Pt() <0 ) ?321 :211;
175 Int_t mcID = TMath::Abs(pTrack->GetLabel());
176 TParticle * part = stack->Particle(TMath::Abs(mcID));
178 info.mcPDG = part->GetPdgCode();
180 if( mcID>=0 ) info.mcMotherID = part->GetFirstMother();
184 //* Construct KFParticle for the track
186 info.fParticle = AliKFParticle( *pTrack, PDG );
190 //* Find event primary vertex
194 const AliKFParticle * vSelected[1000]; //* Selected particles for vertex fit
195 Int_t vIndex[1000]; //* Indices of selected particles
196 Bool_t vFlag[1000]; //* Flags returned by the vertex finder
199 for( Int_t i = 0; i<nESDTracks; i++){
200 if(ESDTrackInfo[i].fOK ){
201 vSelected[nSelected] = &(ESDTrackInfo[i].fParticle);
202 vIndex[nSelected] = i;
206 primVtx.ConstructPrimaryVertex( vSelected, nSelected, vFlag, 3. );
207 for( Int_t i = 0; i<nSelected; i++){
208 if( vFlag[i] ) ESDTrackInfo[vIndex[i]].fPrimUsedFlag = 1;
210 if( primVtx.GetNDF() <1 ) return; //* Less then two tracks in primary vertex
215 for( Int_t iTr = 0; iTr<nESDTracks; iTr++ ){ //* first daughter
217 TESDTrackInfo &info = ESDTrackInfo[iTr];
218 if( !info.fOK ) continue;
220 for( Int_t jTr = iTr+1; jTr<nESDTracks; jTr++ ){ //* second daughter
221 TESDTrackInfo &jnfo = ESDTrackInfo[jTr];
222 if( !jnfo.fOK ) continue;
224 //* check for different charge
226 if( info.fParticle.GetQ() == jnfo.fParticle.GetQ() ) continue;
228 //* construct V0 mother
230 AliKFParticle V0( info.fParticle, jnfo.fParticle );
234 if( V0.GetNDF()<1 ) continue;
235 if( TMath::Sqrt(TMath::Abs(V0.GetChi2()/V0.GetNDF())) >3. ) continue;
237 //* subtruct daughters from primary vertex
239 AliKFVertex primVtxCopy = primVtx;
241 if( info.fPrimUsedFlag ) primVtxCopy -= info.fParticle;
242 if( jnfo.fPrimUsedFlag ) primVtxCopy -= jnfo.fParticle;
244 //* Check V0 Chi^2 deviation from primary vertex
246 if( V0.GetDeviationFromVertex( primVtxCopy ) >3. ) continue;
248 //* Add V0 to primary vertex to improve the primary vertex resolution
252 //* Set production vertex for V0
254 V0.SetProductionVertex( primVtxCopy );
256 //* Check chi^2 for a case
258 if( TMath::Sqrt( TMath::Abs(V0.GetChi2()/V0.GetNDF())) >3. ) continue;
260 //* Get V0 decay length with estimated error
262 Double_t length, sigmaLength;
263 if( V0.GetDecayLength( length, sigmaLength ) ) continue;
265 //* Reject V0 if it decays too close to the primary vertex
267 if( length <3.*sigmaLength ) continue;
269 //* Get V0 invariant mass and plot it
271 Double_t mass, sigmaMass;
272 if( V0.GetMass( mass, sigmaMass ) ) continue;
273 histoMass[0]->Fill(mass);
275 //* Fill signal histograms using MC information
277 if( info.mcMotherID==jnfo.mcMotherID && info.mcMotherID>=0 ){
278 TParticle *mother = stack->Particle(info.mcMotherID);
279 if( mother && TMath::Abs(mother->GetPdgCode())!=21 ){
280 histoMass[1]->Fill(mass);
281 if( mother->GetNDaughters()==2 ){
282 histoMass[2]->Fill(mass);
284 cout<<"PDG V0,pi,pj, ndaughters, mc mass, reco mass = "<<mother->GetPdgCode()<<","<<info.mcPDG<<","<<jnfo.mcPDG<<", "
285 << mother->GetNDaughters()<<", "<<mother->GetMass()<<", "<<mass<<endl;
290 if( iEvent %100 == 0 || (iEvent<100 && iEvent %10==0)) DrawV0();
295 Int_t AliKFParticleTest(Int_t n1=0,Int_t n2=1000,char *dire="/d/alice10/sma/my_v4-05-Release/pp/"){
298 // LOOP OVER SERIES OF DIRECTORIES
300 for (Int_t ifi=n1; ifi<=n2; ifi++) {
302 char nstring[5], filename[100], esdfile[100];
303 sprintf(nstring,"%3.3d",ifi);
304 sprintf(filename,"%s%s/galice.root",dire,nstring);
305 sprintf(esdfile,"%s%s/AliESDs.root",dire,nstring);
307 cout <<" Opening "<<filename<<"\nand ESD "<<esdfile<<endl;
309 TFile* ftemp = TFile::Open(filename);
310 Printf("ftemp = %p", ftemp);
311 if (!ftemp) continue;
314 delete AliRunLoader::Instance();
319 AliRunLoader *rl = AliRunLoader::Open(filename);
321 ::Error("AliKFParticleTest.C","Can not open session !");
324 if (rl->LoadgAlice()) {
325 ::Error("AliKFParticleTest.C","LoadgAlice returned error !");
329 if (rl->LoadHeader()) {
330 ::Error("AliKFParticleTest.C","LoadHeader returned error !");
334 rl->LoadKinematics();
336 //---------------------------------------//
340 //---------------------------------------//
342 // Open file with the ESD
343 TFile *ef=TFile::Open(esdfile);
345 //Check if the file could be opened
346 if (!ef || !ef->IsOpen()) {cerr<<"Error open AliESDs.root !\n"; continue ;}
348 //create event object
349 AliESDEvent *event = new AliESDEvent;
351 //Set pointer to the esd tree in the file
352 TTree* tree = (TTree*) ef->Get("esdTree");
354 //check if the tree exists
355 if (!tree) {cerr<<"no ESD tree found\n"; continue;};
357 //Set pointer to the esd object in the tree
358 event->ReadFromTree(tree);
361 Int_t nevents=tree->GetEntriesFast();
362 cout << "Number of events: " << nevents << endl;
365 for (Int_t iev=0; iev<nevents; iev++){
368 AliKFParticle::SetField(event->GetMagneticField());