4 // This is the universal converter from any kind of source event
5 // (i.e. ESD, standard AOD, MC) into the internal non-standard
6 // AOD format used by RSN package.
8 // This class reads all tracks in an input event and converts them
9 // into AliRsnDaughters, and computes preliminarily the PID probabilities
10 // by doing the Bayesian combination of a set of assigned prior probabilities
11 // with the PID weights defined in each track.
13 // When filling the output event (AliRsnEvent), some arrays of indexes
14 // are created in order to organize tracks according to their PID and charge,
15 // which will then be used in further analysis steps.
17 // author: A. Pulvirenti (alberto.pulvirenti@ct.infn.it)
20 #include <Riostream.h>
25 #include "AliVEvent.h"
27 #include "AliESDEvent.h"
28 #include "AliESDtrack.h"
29 #include "AliESDVertex.h"
30 #include "AliESDtrackCuts.h"
32 #include "AliAODEvent.h"
33 #include "AliAODTrack.h"
34 #include "AliAODVertex.h"
37 #include "AliMCEvent.h"
38 #include "AliMCParticle.h"
39 #include "AliGenEventHeader.h"
41 #include "AliRsnMCInfo.h"
42 #include "AliRsnDaughter.h"
43 #include "AliRsnEvent.h"
44 #include "AliRsnPIDDefESD.h"
45 #include "AliRsnCut.h"
47 #include "AliRsnReader.h"
49 ClassImp(AliRsnReader)
51 //_____________________________________________________________________________
52 AliRsnReader::AliRsnReader() :
56 fUseESDTrackCuts(kFALSE),
57 fUseRsnTrackCuts(kFALSE),
58 fCheckVertexStatus(kFALSE),
68 fRsnTrackCuts("primaryCuts")
75 //_____________________________________________________________________________
76 Bool_t AliRsnReader::AreSplitted(AliESDtrack *track1, AliESDtrack *track2)
79 // Checks if two tracks are splitted.
80 // Currently, two split tracks are the ones which
81 // have equal GEANT labels.
82 // On real data, this criterion will have to change
83 // into an "experimental" one.
86 Int_t lab1 = TMath::Abs(track1->GetLabel());
87 Int_t lab2 = TMath::Abs(track2->GetLabel());
89 return (lab1 == lab2);
92 //_____________________________________________________________________________
93 Bool_t AliRsnReader::ResolveSplit(AliESDtrack *track1, AliESDtrack *track2)
96 // Resolves a split of two tracks.
97 // Only two values can be returned:
98 // kTRUE --> accept "track1" and reject "track2"
99 // kFALSE --> accept "track2" and reject "track1"
102 Double_t chiSq1 = track1->GetConstrainedChi2();
103 Double_t chiSq2 = track2->GetConstrainedChi2();
105 if (chiSq1 < chiSq2) return 1; else return 2;
108 //_____________________________________________________________________________
109 void AliRsnReader::SetTPCOnly(Bool_t doit)
112 // Set the flag for TPC only.
113 // If this is true, exclude all other detectors from PID
119 fPIDDef.ExcludeAll();
120 fPIDDef.IncludeDet(AliRsnPIDDefESD::kTPC);
121 fPIDDef.SetDivValue(AliRsnPIDDefESD::kTPC, 0.0);
125 //_____________________________________________________________________________
126 Bool_t AliRsnReader::ConvertTrack(AliRsnDaughter *daughter, AliESDtrack *esdTrack)
129 // Translates an ESD track into a RSN daughter
133 AliError("Passed NULL object: nothing done");
137 Double_t p[3], v[3], pid[AliRsnPID::kSpecies];
139 // copy values which don't need treatment:
140 // momentum, vertex, chi2, flags, charge, number of TPC and ITS clusters
141 esdTrack->GetPxPyPz(p);
142 daughter->SetP(p[0], p[1], p[2]);
144 daughter->SetV(v[0], v[1], v[2]);
145 daughter->SetChi2(esdTrack->GetConstrainedChi2());
146 daughter->SetFlags(esdTrack->GetStatus());
147 daughter->SetCharge((Short_t)esdTrack->Charge());
148 daughter->SetNumberOfITSClusters(esdTrack->GetITSclusters(0x0));
149 daughter->SetNumberOfTPCClusters(esdTrack->GetTPCclusters(0x0));
151 // define the kink index:
156 for (i = 0; i < 3; i++) ik[i] = esdTrack->GetKinkIndex(i);
157 if (ik[0] < 0 || ik[1] < 0 || ik[2] < 0) daughter->SetKinkMother();
158 else if (ik[0] > 0 || ik[1] > 0 || ik[2] > 0) daughter->SetKinkDaughter();
159 else daughter->SetNoKink();
161 // store PID weights according to definition
162 // check: if the sum of all weights is null, the adoption fails
164 fPIDDef.ComputeWeights(esdTrack, pid);
165 for (i = 0; i < AliRsnPID::kSpecies; i++)
167 daughter->SetPIDWeight(i, pid[i]);
170 if (sum <= 0.0) return kFALSE;
172 // calculate N sigma to vertex
173 AliESDtrackCuts trkCut;
174 daughter->SetNSigmaToVertex(trkCut.GetSigmaToVertex(esdTrack));
179 //_____________________________________________________________________________
180 Bool_t AliRsnReader::ConvertTrack(AliRsnDaughter *daughter, AliAODTrack *aodTrack)
183 // Translates an AOD track into a RSN daughter
188 AliError("Passed NULL object: nothing done");
192 // copy momentum and vertex
193 daughter->SetP(aodTrack->Px(), aodTrack->Py(), aodTrack->Pz());
194 daughter->SetV(aodTrack->Xv(), aodTrack->Yv(), aodTrack->Zv());
197 daughter->SetChi2(aodTrack->Chi2perNDF());
201 for (i = 0; i < 5; i++) daughter->SetPIDWeight(i, aodTrack->PID()[i]);
204 daughter->SetFlags(aodTrack->GetStatus());
207 daughter->SetCharge(aodTrack->Charge());
212 //_____________________________________________________________________________
213 Bool_t AliRsnReader::ConvertTrack(AliRsnDaughter *daughter, TParticle *particle)
216 // Translates an MC particle into a RSN daughter
219 if (!particle) return kFALSE;
221 // copy other MC info (mother PDG code cannot be retrieved here)
222 daughter->InitMCInfo(particle);
224 // copy momentum and vertex
225 daughter->SetP(particle->Px(), particle->Py(), particle->Pz());
226 daughter->SetV(particle->Vx(), particle->Vy(), particle->Vz());
228 // recognize charge sign from PDG code sign
229 Int_t pdg = particle->GetPdgCode();
230 Int_t absPDG = TMath::Abs(pdg);
231 if (absPDG == 11 || absPDG == 13)
233 if (pdg > 0) daughter->SetCharge(-1); else daughter->SetCharge(1);
235 else if (absPDG == 211 || absPDG == 321 || absPDG == 2212)
237 if (pdg > 0) daughter->SetCharge(1); else daughter->SetCharge(-1);
241 // when trying to "adopt" a neutral track (photon, neutron, etc.)
242 // for the moment a "failed" message is returned
246 // flags and PID weights make no sense with MC tracks
247 daughter->SetFlags(0);
248 for (pdg = 0; pdg < AliRsnPID::kSpecies; pdg++) daughter->SetPIDWeight(pdg, 0.0);
249 daughter->SetPIDWeight(AliRsnPID::InternalType(absPDG), 1.0);
254 //_____________________________________________________________________________
255 Bool_t AliRsnReader::Fill
256 (AliRsnEvent *rsn, AliVEvent *event, AliMCEvent *mc)
259 // According to the class type of event and the selected source
260 // recalls one of the private reading methods to fill the RsnEvent
261 // passed by reference as first argument.
264 Bool_t success = kFALSE;
265 TString str(event->ClassName());
267 if (!str.CompareTo("AliESDEvent")) {
268 AliDebug(1, "Reading an ESD event");
269 success = FillFromESD(rsn, (AliESDEvent*)event, mc);
271 else if (!str.CompareTo("AliAODEvent")) {
272 AliDebug(1, "Reading an AOD event");
273 success = FillFromAOD(rsn, (AliAODEvent*)event, mc);
275 else if (!str.CompareTo("AliMCEvent")) {
276 AliDebug(1, "Reading an MC event");
277 success = FillFromMC(rsn, (AliMCEvent*)event);
280 AliError(Form("ClassName '%s' not recognized as possible source data: aborting.", str.Data()));
287 //_____________________________________________________________________________
288 Bool_t AliRsnReader::FillFromESD(AliRsnEvent *rsn, AliESDEvent *esd, AliMCEvent *mc)
291 // Filler from an ESD event.
292 // Stores all tracks (if a filter is defined, it will store
293 // only the ones which survive the cuts).
294 // If a reference MC event is provided, it is used to store
295 // the MC informations for each track (true PDG code,
296 // GEANT label of mother, PDG code of mother, if any).
297 // When this is used, the 'source' flag of the output
298 // AliRsnEvent object will be set to 'kESD'.
301 // retrieve stack (if possible)
302 AliStack *stack = 0x0;
303 if (mc) stack = mc->Stack();
305 // set MC primary vertex if present
307 Double_t mcvx = 0., mcvy = 0., mcvz = 0.;
309 mc->GenEventHeader()->PrimaryVertex(fvertex);
310 mcvx = (Double_t)fvertex[0];
311 mcvy = (Double_t)fvertex[1];
312 mcvz = (Double_t)fvertex[2];
313 rsn->SetPrimaryVertexMC(mcvx, mcvy, mcvz);
316 // get number of tracks
317 Int_t ntracks = esd->GetNumberOfTracks();
318 if (!ntracks) return kFALSE;
320 // if required with the flag, scans the event
321 // and searches all split tracks (= 2 tracks with the same label);
322 // for each pair of split tracks, only the better (best chi2) is kept
323 // and the other is rejected: this info is stored into a Boolean array
325 Bool_t *accept = new Bool_t[ntracks];
326 for (i = 0; i < ntracks; i++) accept[i] = kTRUE;
328 for (i1 = 0; i1 < ntracks; i1++) {
329 AliESDtrack *track1 = esd->GetTrack(i1);
330 for (i2 = i1 + 1; i2 < ntracks; i2++) {
331 AliESDtrack *track2 = esd->GetTrack(i2);
332 if (AreSplitted(track1, track2)) {
333 if (ResolveSplit(track1, track2)) accept[i2] = kFALSE;
334 else accept[i1] = kFALSE;
340 // get primary vertex
343 // when taking vertex from ESD event there are two options:
344 // if a vertex with tracks was successfully reconstructed,
345 // it is used for computing DCA;
346 // otherwise, the one computed with SPD is used.
347 // This is known from the "Status" parameter of the vertex itself.
348 const AliESDVertex *v = esd->GetPrimaryVertex();
349 if (!v->GetStatus()) v = esd->GetPrimaryVertexSPD();
350 if (fCheckVertexStatus && v->GetStatus() == kFALSE) return kFALSE;
351 if (fMinNContributors > 0 && v->GetNContributors() < fMinNContributors) return kFALSE;
353 // get primary vertex
354 vertex[0] = (Double_t)v->GetXv();
355 vertex[1] = (Double_t)v->GetYv();
356 vertex[2] = (Double_t)v->GetZv();
359 const AliESDVertex *v = esd->GetPrimaryVertexTPC();
360 if (fCheckVertexStatus && v->GetStatus() == kFALSE) return kFALSE;
361 if (fMinNContributors > 0 && v->GetNContributors() < fMinNContributors) return kFALSE;
363 // get primary vertex
364 vertex[0] = (Double_t)v->GetXv();
365 vertex[1] = (Double_t)v->GetYv();
366 vertex[2] = (Double_t)v->GetZv();
368 rsn->SetPrimaryVertex(vertex[0], vertex[1], vertex[2]);
370 // store tracks from ESD
371 Float_t p[2], cov[3];
372 Int_t index, label, labmum;
375 AliESDtrack *esdTrack = 0x0, esdTrackTmp;
376 for (index = 0; index < ntracks; index++) {
377 // skip track recognized as the worse one in a splitted pair
378 if (!accept[index]) {
379 AliDebug(10, Form("Rejecting split track #%d in this event", index));
383 esdTrack = esd->GetTrack(index);
384 // check for ESD track cuts (if required)
385 if (fUseESDTrackCuts && (!fESDTrackCuts.AcceptTrack(esdTrack))) continue;
386 // check for fake tracks
387 label = esdTrack->GetLabel();
388 if (fRejectFakes && (label < 0)) continue;
389 // check for minimum number of clusters in ITS, TPC and TRD
390 if (fITSClusters > 0 && (esdTrack->GetITSclusters(0x0) < fITSClusters)) if (!fTPCOnly) continue;
391 if (fTPCClusters > 0 && (esdTrack->GetTPCclusters(0x0) < fTPCClusters)) continue;
392 if (fTRDClusters > 0 && (esdTrack->GetTRDclusters(0x0) < fTRDClusters)) if (!fTPCOnly) continue;
393 // switch to TPC data if required
395 esdTrack->GetImpactParametersTPC(p, cov);
396 if (p[0] == 0. && p[1] == 0.) {
397 esdTrack->RelateToVertexTPC(esd->GetPrimaryVertexTPC(), esd->GetMagneticField(), kVeryBig);
399 check = esdTrack->FillTPCOnlyTrack(esdTrackTmp);
400 if (check) esdTrack = &esdTrackTmp; else continue;
402 // try to get information from this track
403 // output value tells if this was successful or not
404 check = ConvertTrack(&temp, esdTrack);
406 AliDebug(10, Form("Failed adopting track #%d", index));
410 // if stack is present, copy MC info
412 TParticle *part = stack->Particle(TMath::Abs(label));
414 temp.InitMCInfo(part);
415 labmum = part->GetFirstMother();
417 TParticle *mum = stack->Particle(labmum);
418 temp.GetMCInfo()->SetMotherPDG(mum->GetPdgCode());
423 // set index and label
424 temp.SetIndex(index);
425 temp.SetLabel(label);
427 // check this object against the Rsn cuts (if required)
428 if (fUseRsnTrackCuts) {
429 if (!fRsnTrackCuts.IsSelected(AliRsnCut::kParticle, &temp)) continue;
432 // try to add track to collection and returns an error in case of problems
433 AliRsnDaughter *ptr = rsn->AddTrack(temp);
434 if (!ptr) AliWarning(Form("Failed storing track#%d", index));
437 // compute total multiplicity
438 rsn->MakeComputations();
439 if (rsn->GetMultiplicity() <= 0) {
440 AliDebug(1, "Zero Multiplicity in this event");
444 // sort tracks w.r. to Pt (from largest to smallest)
447 // correct tracks for primary vertex
448 //rsn->CorrectTracks();
453 //_____________________________________________________________________________
454 Bool_t AliRsnReader::FillFromAOD(AliRsnEvent *rsn, AliAODEvent *aod, AliMCEvent *mc)
457 // Filler from an AOD event.
458 // Stores all tracks (if a filter is defined, it will store
459 // only the ones which survive the cuts).
460 // If a reference MC event is provided, it is used to store
461 // the MC informations for each track (true PDG code,
462 // GEANT label of mother, PDG code of mother, if any).
463 // When this is used, the 'source' flag of the output
464 // AliRsnEvent object will be set to 'kAOD'.
467 // retrieve stack (if possible)
468 AliStack *stack = 0x0;
469 if (mc) stack = mc->Stack();
471 // get number of tracks
472 Int_t ntracks = aod->GetNTracks();
473 if (!ntracks) return kFALSE;
475 // get primary vertex
477 vertex[0] = aod->GetPrimaryVertex()->GetX();
478 vertex[1] = aod->GetPrimaryVertex()->GetY();
479 vertex[2] = aod->GetPrimaryVertex()->GetZ();
480 rsn->SetPrimaryVertex(vertex[0], vertex[1], vertex[2]);
482 // set MC primary vertex if present
484 Double_t mcvx = 0., mcvy = 0., mcvz = 0.;
486 mc->GenEventHeader()->PrimaryVertex(fvertex);
487 mcvx = (Double_t)fvertex[0];
488 mcvy = (Double_t)fvertex[1];
489 mcvz = (Double_t)fvertex[2];
490 rsn->SetPrimaryVertexMC(mcvx, mcvy, mcvz);
493 // store tracks from ESD
494 Int_t index, label, labmum;
496 AliAODTrack *aodTrack = 0;
498 TObjArrayIter iter(aod->GetTracks());
499 while ((aodTrack = (AliAODTrack*)iter.Next()))
502 index = aod->GetTracks()->IndexOf(aodTrack);
503 label = aodTrack->GetLabel();
504 if (fRejectFakes && (label < 0)) continue;
505 // copy ESD track data into RsnDaughter
506 // if unsuccessful, this track is skipped
507 check = ConvertTrack(&temp, aodTrack);
508 if (!check) continue;
509 // if stack is present, copy MC info
512 TParticle *part = stack->Particle(TMath::Abs(label));
515 temp.InitMCInfo(part);
516 labmum = part->GetFirstMother();
519 TParticle *mum = stack->Particle(labmum);
520 temp.GetMCInfo()->SetMotherPDG(mum->GetPdgCode());
524 // set index and label and add this object to the output container
525 temp.SetIndex(index);
526 temp.SetLabel(label);
528 // check this object against the Rsn cuts (if required)
529 if (fUseRsnTrackCuts) {
530 if (!fRsnTrackCuts.IsSelected(AliRsnCut::kParticle, &temp)) continue;
533 AliRsnDaughter *ptr = rsn->AddTrack(temp);
534 // if problems occurred while storin, that pointer is NULL
535 if (!ptr) AliWarning(Form("Failed storing track#%d"));
538 // compute total multiplicity
539 rsn->MakeComputations();
540 if (rsn->GetMultiplicity() <= 0)
542 AliDebug(1, "Zero multiplicity in this event");
546 // correct tracks for primary vertex
547 rsn->CorrectTracks();
552 //_____________________________________________________________________________
553 Bool_t AliRsnReader::FillFromMC(AliRsnEvent *rsn, AliMCEvent *mc)
556 // Filler from an ESD event.
557 // Stores all tracks which generate at least one
558 // TrackReference (a point in a sensitive volume).
559 // In this case, the MC info is stored by default and
560 // perfect particle identification is the unique available.
561 // When this is used, the 'source' flag of the output
562 // AliRsnEvent object will be set to 'kMC'.
565 // get number of tracks
566 Int_t ntracks = mc->GetNumberOfTracks();
567 if (!ntracks) return kFALSE;
569 AliStack *stack = mc->Stack();
571 // get primary vertex
574 mc->GenEventHeader()->PrimaryVertex(fvertex);
575 vx = (Double_t)fvertex[0];
576 vy = (Double_t)fvertex[1];
577 vz = (Double_t)fvertex[2];
578 rsn->SetPrimaryVertex(vx, vy, vz);
579 rsn->SetPrimaryVertexMC(vx, vy, vz);
581 // store tracks from MC
582 Int_t i, index, labmum, nRef, nRefITS, nRefTPC, detectorID;
584 for (index = 0; index < ntracks; index++)
586 // get MC track & take index and label
587 AliMCParticle *mcTrack = mc->GetTrack(index);
588 temp.SetIndex(index);
589 temp.SetLabel(mcTrack->Label());
591 // check particle track references
592 nRef = mcTrack->GetNumberOfTrackReferences();
593 for (i = 0, nRefITS = 0, nRefTPC = 0; i < nRef; i++) {
594 AliTrackReference *trackRef = mcTrack->GetTrackReference(i);
595 if (!trackRef) continue;
596 detectorID = trackRef->DetectorId();
597 switch (detectorID) {
598 case AliTrackReference::kITS : nRefITS++; break;
599 case AliTrackReference::kTPC : nRefTPC++; break;
603 if (fTrackRefs > 0 && nRef < fTrackRefs) continue;
604 if (fTrackRefsITS > 0 && nRefITS < fTrackRefsITS) continue;
605 if (fTrackRefsTPC > 0 && nRefTPC < fTrackRefsTPC) continue;
607 // try to insert in the RsnDaughter its data
608 TParticle *mcPart = mcTrack->Particle();
609 if (!ConvertTrack(&temp, mcPart)) continue;
611 // assign mother label and PDG code (if any)
612 labmum = temp.GetMCInfo()->Mother();
614 TParticle *mum = stack->Particle(labmum);
615 temp.GetMCInfo()->SetMotherPDG(mum->GetPdgCode());
618 // check this object against the Rsn cuts (if required)
619 if (fUseRsnTrackCuts) {
620 if (!fRsnTrackCuts.IsSelected(AliRsnCut::kParticle, &temp)) continue;
623 AliRsnDaughter *ptr = rsn->AddTrack(temp);
624 if (!ptr) AliWarning(Form("Failed storing track #%d", index));
627 // compute total multiplicity
628 rsn->MakeComputations();
629 if (rsn->GetMultiplicity() <= 0)
631 AliDebug(1, "Zero multiplicity in this event");
635 // sort tracks w.r. to Pt (from largest to smallest)
638 // correct tracks for primary vertex
639 rsn->CorrectTracks();