1 // This is an example macro which loops on all ESD events in a file set
2 // and stores the selected information in form of mini ESD tree.
3 // It also extracts the corresponding MC information in a parallel MC tree.
5 // Input: galice.root,Kinematics.root,AliESDs.root (read only)
6 // Output: miniesd.root (recreate)
8 // Usage: faster if compiled
9 // gSystem->SetIncludePath("-I$ROOTSYS/include -I$ALICE_ROOT/include -I$ALICE_ROOT/TPC");
10 // gROOT->LoadMacro("mcminiesd.C+");
13 // Author: Peter Hristov
14 // e-mail: Peter.Hristov@cern.ch
16 #if !defined(__CINT__) || defined(__MAKECINT__)
19 #include <Riostream.h>
23 #include <TStopwatch.h>
25 #include <TParticle.h>
26 #include <TLorentzVector.h>
29 #include <TDatabasePDG.h>
30 #include <TParticlePDG.h>
32 // AliRoot include files
34 #include "AliESDVertex.h"
35 #include "AliRunLoader.h"
38 #include "AliHeader.h"
39 #include "AliGenEventHeader.h"
40 #include "AliTPCtrack.h"
44 void selectRecTracks(AliESD* esdOut, Int_t * select, Int_t &nkeep0) {
45 // Select also all the reconstructed tracks in case it was not done before
46 Int_t nrec = esdOut->GetNumberOfTracks();
47 for(Int_t irec=0; irec<nrec; irec++) {
48 AliESDtrack * track = esdOut->GetTrack(irec);
49 UInt_t label = TMath::Abs(track->GetLabel());
50 if (label>=10000000) continue; // Underlying event. 10000000 is the
51 // value of fkMASKSTEP in AliRunDigitizer
59 void copyGeneralESDInfo(AliESD* esdIn, AliESD* esdOut) {
60 // Event and run number
61 esdOut->SetEventNumber(esdIn->GetEventNumber());
62 esdOut->SetRunNumber(esdIn->GetRunNumber());
65 esdOut->SetTrigger(esdIn->GetTrigger());
68 esdOut->SetMagneticField(esdIn->GetMagneticField());
71 const AliESDVertex * vtxIn = esdIn->GetVertex();
75 vtxIn->GetCovMatrix(cov);
77 AliESDVertex * vtxOut = new AliESDVertex(pos,cov,
79 vtxIn->GetNContributors());
81 vtxIn->GetTruePos(tp);
82 vtxOut->SetTruePos(tp);
84 esdOut->SetVertex(vtxOut);
87 void selectMiniESD(AliESD* esdIn, AliESD* &esdOut) {
88 // This function copies the general ESD information
89 // and selects the reconstructed tracks of interest
90 // The second argument is a reference to pointer since we
91 // want to operate not with the content, but with the pointer itself
93 printf("--------------------\n");
94 printf("Selecting data mini ESD\n");
98 // Create the new output ESD
99 esdOut = new AliESD();
101 // Copy the general information
102 copyGeneralESDInfo(esdIn, esdOut);
105 Int_t ntrk = esdIn->GetNumberOfTracks();
108 for (Int_t itrk=0; itrk<ntrk; itrk++) {
110 AliESDtrack * trackIn = esdIn->GetTrack(itrk);
111 UInt_t status=trackIn->GetStatus();
113 //select only tracks with TPC or ITS refit
114 if ((status&AliESDtrack::kTPCrefit)==0
115 && (status&AliESDtrack::kITSrefit)==0
118 //select only tracks with "combined" PID
119 if ((status&AliESDtrack::kESDpid)==0) continue;
121 AliESDtrack * trackOut = new AliESDtrack(*trackIn);
123 // Reset most of the redundant information
124 trackOut->MakeMiniESDtrack();
126 esdOut->AddTrack(trackOut);
128 // Do not delete trackIn, it is a second pointer to an
129 // object belonging to the TClonesArray
133 printf("%d tracks selected\n",esdOut->GetNumberOfTracks());
137 printf("--------------------\n");
140 void fixMotherDaughter(TClonesArray& particles, Int_t * map) {
141 // Fix mother-daughter relationship
142 // using the map of old to new indexes
143 Int_t nkeep = particles.GetEntriesFast();
144 for (Int_t i=0; i<nkeep; i++) {
145 TParticle * part = (TParticle*)particles[i];
148 Int_t mum = part->GetFirstMother();
149 if (mum>-1 && i>map[mum])
150 part->SetFirstMother(map[mum]);
153 Int_t fd = part->GetFirstDaughter();
154 Int_t ld = part->GetLastDaughter();
156 // invalidate daughters
157 part->SetFirstDaughter(-1);
158 part->SetLastDaughter(-1);
160 for (Int_t id=TMath::Max(fd,0); id<=ld; id++) {
162 // this daughter was selected
163 if(part->GetFirstDaughter() < 0) part->SetFirstDaughter(map[id]);
164 part->SetLastDaughter(map[id]);
170 void checkConsistency(TClonesArray& particles) {
172 // each mother is before the daughters,
173 // each daughter from the mother's list
174 // points back to its mother
175 Int_t nkeep = particles.GetEntriesFast();
176 for (Int_t i=0; i<nkeep; i++) {
177 TParticle * part = (TParticle*)particles[i];
179 Int_t mum = part->GetFirstMother();
181 if (mum>-1 && i<mum) {
182 cout << "Problem: mother " << mum << " after daughter " << i << endl;
185 Int_t fd = part->GetFirstDaughter();
186 Int_t ld = part->GetLastDaughter();
188 if (fd > ld ) cout << "Problem " << fd << " > " << ld << endl;
189 if (fd > -1 && fd < i )
190 cout << "Problem: mother " << i << " after daughter " << ld << endl;
192 for (Int_t id=TMath::Max(fd,0); id<=ld; id++) {
193 TParticle * daughter = (TParticle*)particles[id];
194 if (daughter->GetFirstMother() != i) {
195 cout << "Problem "<< i << " not "
196 << daughter->GetFirstMother() << endl;
205 void kinetree(AliRunLoader* runLoader, AliESD* &esdOut, TClonesArray* &ministack) {
207 printf("--------------------\n");
208 printf("Selecting MC mini ESD\n");
212 // Particle properties
213 TDatabasePDG * pdgdb = TDatabasePDG::Instance();
216 AliStack * stack = runLoader->Stack();
218 Int_t npart = stack->GetNtrack();
220 // Particle momentum and vertex. Will be extracted from TParticle
221 TLorentzVector momentum;
223 runLoader->GetHeader()->GenEventHeader()->PrimaryVertex(vertex);
226 // Counter for selected particles
229 Int_t * select = new Int_t[npart];
231 // Loop on particles: physics selection
232 for (Int_t ipart=0; ipart<npart; ipart++) {
236 TParticle * part = stack->Particle(ipart);
239 cout << "Empty particle " << ipart << endl;
243 // Particle momentum and vertex of origin
244 part->Momentum(momentum);
245 dvertex.SetXYZ(part->Vx()-vertex[0],
246 part->Vy()-vertex[1],
247 part->Vz()-vertex[2]);
249 // Now select only the "interesting" particles
251 // Select all particles from the primary vertex:
252 // resonances and products of resonance decays
253 if(dvertex.Mag()<0.0001) {
259 // Reject particles born outside ITS
260 if (dvertex.Perp()>100) continue;
262 // Reject particles with too low momentum, they don't rich TPC
263 if (part->Pt()<0.1) continue;
265 // Reject "final state" neutral particles
266 // This has to be redone after this loop
267 Int_t pdgcode = part->GetPdgCode();
268 TParticlePDG * pdgpart = pdgdb->GetParticle(pdgcode);
270 if (pdgpart) charge = (Int_t) pdgpart->Charge();
273 if (part->GetFirstDaughter()<0) continue;
276 // Select the rest of particles except the case
277 // particle -> particle + X
278 // for example bremstrahlung and delta electrons
279 Int_t mumid = part->GetFirstMother();
280 TParticle * mother = stack->Particle(mumid);
282 Int_t mumpdg = mother->GetPdgCode();
283 Bool_t skip = kFALSE;
284 for (Int_t id=mother->GetFirstDaughter();
285 id<=mother->GetLastDaughter();
287 TParticle * daughter=stack->Particle(id);
288 if (!daughter) continue;
289 if (mumpdg == daughter->GetPdgCode()) {
297 // All the criteria are OK, this particle is selected
301 } // end loop over particles in the current event
303 selectRecTracks(esdOut, select, nkeep0);
305 // Container for the selected particles
306 TClonesArray * pparticles = new TClonesArray("TParticle",nkeep0);
307 TClonesArray &particles = *pparticles;
309 // Map of the indexes in the stack and the new ones in the TClonesArray
310 Int_t * map = new Int_t[npart];
312 // Counter for selected particles
315 for (Int_t ipart=0; ipart<npart; ipart++) {
317 map[ipart] = -99; // Reset the map
321 TParticle * part = stack->Particle(ipart);
323 new(particles[nkeep++]) TParticle(*part);
328 if (nkeep0 != nkeep) printf("Strange %d is not %d\n",nkeep0,nkeep);
332 // Fix mother-daughter relationship
333 fixMotherDaughter(particles,map);
336 checkConsistency(particles);
338 // Now remove the "final state" neutral particles
340 TClonesArray * particles1 = new TClonesArray("TParticle",nkeep);
341 Int_t * map1 = new Int_t[nkeep];
345 for (Int_t ipart=0; ipart<nkeep; ipart++) {
347 map1[ipart] = -99; // Reset the map
349 TParticle * part = (TParticle*)particles[ipart];
351 // Reject "final state" neutral particles
352 // This has to be redone after this loop
353 Int_t pdgcode = part->GetPdgCode();
354 TParticlePDG * pdgpart = pdgdb->GetParticle(pdgcode);
356 if (pdgpart) charge = (Int_t) pdgpart->Charge();
359 if (part->GetFirstDaughter()<0) continue;
362 // Select the particle
363 map1[ipart] = nkeep1;
364 TClonesArray &ar = *particles1;
365 new(ar[nkeep1++]) TParticle(*part);
370 cout << nkeep1 << " particles finally selected" << endl;
372 fixMotherDaughter(*particles1,map1);
373 checkConsistency(*particles1);
375 // Remap the labels of reconstructed tracks
377 AliESD * esdNew = new AliESD();
379 copyGeneralESDInfo(esdOut,esdNew);
381 // Needed by the TPC track
382 AliKalmanTrack::SetConvConst(1000/0.299792458/esdOut->GetMagneticField());
385 Int_t nrec = esdOut->GetNumberOfTracks();
386 for(Int_t irec=0; irec<nrec; irec++) {
387 AliESDtrack * track = esdOut->GetTrack(irec);
388 UInt_t label = TMath::Abs(track->GetLabel());
389 if (label<10000000) { // Signal event. 10000000 is the
390 // value of fkMASKSTEP in AliRunDigitizer
391 track->SetLabel(TMath::Sign(map1[map[label]],track->GetLabel()));
393 esdNew->AddTrack(track);
399 ministack = particles1;
408 printf("--------------------\n");
413 AliTPCtrack * particle2track(TParticle * part) {
415 // Converts TParticle to AliTPCtrack
423 // Calculate alpha: the rotation angle of the corresponding TPC sector
424 alpha = part->Phi()*180./TMath::Pi();
425 if (alpha<0) alpha+= 360.;
426 if (alpha>360) alpha -= 360.;
428 Int_t sector = (Int_t)(alpha/20.);
429 alpha = 10. + 20.*sector;
431 alpha *= TMath::Pi();
434 // Reset the covariance matrix
435 for (Int_t i=0; i<15; i++) cc[i]=0.;
439 index = part->GetUniqueID();
441 // Get the vertex of origin and the momentum
442 TVector3 ver(part->Vx(),part->Vy(),part->Vz());
443 TVector3 mom(part->Px(),part->Py(),part->Pz());
446 // Rotate to the local (sector) coordinate system
450 // X of the referense plane
454 // fX = xref X-coordinate of this track (reference plane)
455 // fAlpha = Alpha Rotation angle the local (TPC sector)
456 // fP0 = YL Y-coordinate of a track
457 // fP1 = ZG Z-coordinate of a track
458 // fP2 = C*x0 x0 is center x in rotated frame
459 // fP3 = Tgl tangent of the track momentum dip angle
460 // fP4 = C track curvature
463 TVector3 field(0.,0.,1/AliKalmanTrack::GetConvConst());
464 // radius [cm] of track projection in (x,y)
466 mom.Pt()*AliKalmanTrack::GetConvConst();
469 TDatabasePDG::Instance()->GetParticle(part->GetPdgCode())->Charge();
472 if (TMath::Abs(charge) < 0.9) charge=1.e-9;
474 TVector3 vrho = mom.Cross(field);
479 Double_t x0 = vrho.X();
483 xx[3] = mom.Pz()/mom.Pt();
486 // if (TMath::Abs(charge) < 0.9) xx[4] = 0;
488 AliTPCtrack * tr = new AliTPCtrack(index, xx, cc, xref, alpha);
496 printf("====================\n");
497 printf("Main program\n");
501 // Input "data" file, tree, and branch
502 TFile * fIn = TFile::Open("AliESDs.root");
503 TTree * tIn = (TTree*)fIn->Get("esdTree");
504 TBranch * bIn = tIn->GetBranch("ESD");
506 AliESD * esdIn = 0; // The input ESD object is put here
507 bIn->SetAddress(&esdIn);
509 // Output file, trees, and branches.
510 // Both "data" and MC are stored in the same file
511 TFile * fOut = TFile::Open("miniesd.root","recreate");
512 TTree * tOut = new TTree("esdTree","esdTree");
513 TTree * tMC = new TTree("mcStackTree","mcStackTree");
515 AliESD * esdOut = 0; // The newly created ESD object
516 TBranch * bOut = tOut->Branch("ESD","AliESD",&esdOut);
517 bOut->SetCompressionLevel(9);
519 // TParticles are stored in TClonesArray
520 // The corresponding branch is created using "dummy" TClonesArray
521 TClonesArray * ministack = new TClonesArray("TParticle");
522 TBranch * bMC = tMC->Branch("Stack",&ministack);
525 bMC->SetCompressionLevel(9);
528 AliHeader * headerIn = 0; //
529 TBranch * bHeader = tMC->Branch("Header","AliHeader",&headerIn);
530 bHeader->SetCompressionLevel(9);
533 AliRunLoader* runLoader = AliRunLoader::Open("galice.root");
536 runLoader->LoadgAlice();
537 gAlice = runLoader->GetAliRun();
539 // Now load kinematics and event header
540 runLoader->LoadKinematics();
541 runLoader->LoadHeader();
543 // Loop on events: check that MC and data contain the same number of events
544 Int_t nevESD = bIn->GetEntries();
545 Int_t nevMC = (Int_t)runLoader->GetNumberOfEvents();
548 cout << "Inconsistent number of ESD("<<nevESD<<") and MC("<<nevMC<<") events" << endl;
551 Int_t nev=TMath::Min(nevMC,nevESD);
553 cout << nev << " events to process" << endl;
555 for (Int_t iev=0; iev<nev; iev++) {
556 cout << "Event " << iev << endl;
561 selectMiniESD(esdIn,esdOut);
564 runLoader->GetEvent(iev);
567 kinetree(runLoader,esdOut,ministack);
568 bMC->SetAddress(&ministack); // needed because ministack has changed
571 headerIn = runLoader->GetHeader();
585 fOut = tOut->GetCurrentFile();
593 printf("====================\n");