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),
66 fRsnTrackCuts("primaryCuts")
73 //_____________________________________________________________________________
74 Bool_t AliRsnReader::AreSplitted(AliESDtrack *track1, AliESDtrack *track2)
77 // Checks if two tracks are splitted.
78 // Currently, two split tracks are the ones which
79 // have equal GEANT labels.
80 // On real data, this criterion will have to change
81 // into an "experimental" one.
84 Int_t lab1 = TMath::Abs(track1->GetLabel());
85 Int_t lab2 = TMath::Abs(track2->GetLabel());
87 return (lab1 == lab2);
90 //_____________________________________________________________________________
91 Bool_t AliRsnReader::ResolveSplit(AliESDtrack *track1, AliESDtrack *track2)
94 // Resolves a split of two tracks.
95 // Only two values can be returned:
96 // kTRUE --> accept "track1" and reject "track2"
97 // kFALSE --> accept "track2" and reject "track1"
100 Double_t chiSq1 = track1->GetConstrainedChi2();
101 Double_t chiSq2 = track2->GetConstrainedChi2();
103 if (chiSq1 < chiSq2) return 1; else return 2;
106 //_____________________________________________________________________________
107 void AliRsnReader::SetTPCOnly(Bool_t doit)
110 // Set the flag for TPC only.
111 // If this is true, exclude all other detectors from PID
117 fPIDDef.ExcludeAll();
118 fPIDDef.IncludeDet(AliRsnPIDDefESD::kTPC);
119 fPIDDef.SetDivValue(AliRsnPIDDefESD::kTPC, 0.0);
123 //_____________________________________________________________________________
124 Bool_t AliRsnReader::ConvertTrack(AliRsnDaughter *daughter, AliESDtrack *esdTrack)
127 // Translates an ESD track into a RSN daughter
131 AliError("Passed NULL object: nothing done");
135 Double_t p[3], v[3], pid[AliRsnPID::kSpecies];
137 // copy values which don't need treatment:
138 // momentum, vertex, chi2, flags, charge, number of TPC and ITS clusters
139 esdTrack->GetPxPyPz(p);
140 daughter->SetP(p[0], p[1], p[2]);
142 daughter->SetV(v[0], v[1], v[2]);
143 daughter->SetChi2(esdTrack->GetConstrainedChi2());
144 daughter->SetFlags(esdTrack->GetStatus());
145 daughter->SetCharge((Short_t)esdTrack->Charge());
146 daughter->SetNumberOfITSClusters(esdTrack->GetITSclusters(0x0));
147 daughter->SetNumberOfTPCClusters(esdTrack->GetTPCclusters(0x0));
149 // define the kink index:
154 for (i = 0; i < 3; i++) ik[i] = esdTrack->GetKinkIndex(i);
155 if (ik[0] < 0 || ik[1] < 0 || ik[2] < 0) daughter->SetKinkMother();
156 else if (ik[0] > 0 || ik[1] > 0 || ik[2] > 0) daughter->SetKinkDaughter();
157 else daughter->SetNoKink();
159 // store PID weights according to definition
160 // check: if the sum of all weights is null, the adoption fails
162 fPIDDef.ComputeWeights(esdTrack, pid);
163 for (i = 0; i < AliRsnPID::kSpecies; i++)
165 daughter->SetPIDWeight(i, pid[i]);
168 if (sum <= 0.0) return kFALSE;
170 // calculate N sigma to vertex
171 AliESDtrackCuts trkCut;
172 daughter->SetNSigmaToVertex(trkCut.GetSigmaToVertex(esdTrack));
177 //_____________________________________________________________________________
178 Bool_t AliRsnReader::ConvertTrack(AliRsnDaughter *daughter, AliAODTrack *aodTrack)
181 // Translates an AOD track into a RSN daughter
186 AliError("Passed NULL object: nothing done");
190 // copy momentum and vertex
191 daughter->SetP(aodTrack->Px(), aodTrack->Py(), aodTrack->Pz());
192 daughter->SetV(aodTrack->Xv(), aodTrack->Yv(), aodTrack->Zv());
195 daughter->SetChi2(aodTrack->Chi2perNDF());
199 for (i = 0; i < 5; i++) daughter->SetPIDWeight(i, aodTrack->PID()[i]);
202 daughter->SetFlags(aodTrack->GetStatus());
205 daughter->SetCharge(aodTrack->Charge());
210 //_____________________________________________________________________________
211 Bool_t AliRsnReader::ConvertTrack(AliRsnDaughter *daughter, TParticle *particle)
214 // Translates an MC particle into a RSN daughter
217 if (!particle) return kFALSE;
219 // copy other MC info (mother PDG code cannot be retrieved here)
220 daughter->InitMCInfo(particle);
222 // copy momentum and vertex
223 daughter->SetP(particle->Px(), particle->Py(), particle->Pz());
224 daughter->SetV(particle->Vx(), particle->Vy(), particle->Vz());
226 // recognize charge sign from PDG code sign
227 Int_t pdg = particle->GetPdgCode();
228 Int_t absPDG = TMath::Abs(pdg);
229 if (absPDG == 11 || absPDG == 13)
231 if (pdg > 0) daughter->SetCharge(-1); else daughter->SetCharge(1);
233 else if (absPDG == 211 || absPDG == 321 || absPDG == 2212)
235 if (pdg > 0) daughter->SetCharge(1); else daughter->SetCharge(-1);
239 // when trying to "adopt" a neutral track (photon, neutron, etc.)
240 // for the moment a "failed" message is returned
244 // flags and PID weights make no sense with MC tracks
245 daughter->SetFlags(0);
246 for (pdg = 0; pdg < AliRsnPID::kSpecies; pdg++) daughter->SetPIDWeight(pdg, 0.0);
247 daughter->SetPIDWeight(AliRsnPID::InternalType(absPDG), 1.0);
252 //_____________________________________________________________________________
253 Bool_t AliRsnReader::Fill
254 (AliRsnEvent *rsn, AliVEvent *event, AliMCEvent *mc)
257 // According to the class type of event and the selected source
258 // recalls one of the private reading methods to fill the RsnEvent
259 // passed by reference as first argument.
262 Bool_t success = kFALSE;
263 TString str(event->ClassName());
265 if (!str.CompareTo("AliESDEvent")) {
266 AliDebug(1, "Reading an ESD event");
267 success = FillFromESD(rsn, (AliESDEvent*)event, mc);
269 else if (!str.CompareTo("AliAODEvent")) {
270 AliDebug(1, "Reading an AOD event");
271 success = FillFromAOD(rsn, (AliAODEvent*)event, mc);
273 else if (!str.CompareTo("AliMCEvent")) {
274 AliDebug(1, "Reading an MC event");
275 success = FillFromMC(rsn, (AliMCEvent*)event);
278 AliError(Form("ClassName '%s' not recognized as possible source data: aborting.", str.Data()));
285 //_____________________________________________________________________________
286 Bool_t AliRsnReader::FillFromESD(AliRsnEvent *rsn, AliESDEvent *esd, AliMCEvent *mc)
289 // Filler from an ESD event.
290 // Stores all tracks (if a filter is defined, it will store
291 // only the ones which survive the cuts).
292 // If a reference MC event is provided, it is used to store
293 // the MC informations for each track (true PDG code,
294 // GEANT label of mother, PDG code of mother, if any).
295 // When this is used, the 'source' flag of the output
296 // AliRsnEvent object will be set to 'kESD'.
299 // retrieve stack (if possible)
300 AliStack *stack = 0x0;
301 if (mc) stack = mc->Stack();
303 // set MC primary vertex if present
305 Double_t mcvx = 0., mcvy = 0., mcvz = 0.;
307 mc->GenEventHeader()->PrimaryVertex(fvertex);
308 mcvx = (Double_t)fvertex[0];
309 mcvy = (Double_t)fvertex[1];
310 mcvz = (Double_t)fvertex[2];
311 rsn->SetPrimaryVertexMC(mcvx, mcvy, mcvz);
314 // get number of tracks
315 Int_t ntracks = esd->GetNumberOfTracks();
316 if (!ntracks) return kFALSE;
318 // if required with the flag, scans the event
319 // and searches all split tracks (= 2 tracks with the same label);
320 // for each pair of split tracks, only the better (best chi2) is kept
321 // and the other is rejected: this info is stored into a Boolean array
323 Bool_t *accept = new Bool_t[ntracks];
324 for (i = 0; i < ntracks; i++) accept[i] = kTRUE;
326 for (i1 = 0; i1 < ntracks; i1++) {
327 AliESDtrack *track1 = esd->GetTrack(i1);
328 for (i2 = i1 + 1; i2 < ntracks; i2++) {
329 AliESDtrack *track2 = esd->GetTrack(i2);
330 if (AreSplitted(track1, track2)) {
331 if (ResolveSplit(track1, track2)) accept[i2] = kFALSE;
332 else accept[i1] = kFALSE;
338 // get primary vertex
341 // when taking vertex from ESD event there are two options:
342 // if a vertex with tracks was successfully reconstructed,
343 // it is used for computing DCA;
344 // otherwise, the one computed with SPD is used.
345 // This is known from the "Status" parameter of the vertex itself.
346 const AliESDVertex *v = esd->GetPrimaryVertex();
347 if (!v->GetStatus()) v = esd->GetPrimaryVertexSPD();
349 // get primary vertex
350 vertex[0] = (Double_t)v->GetXv();
351 vertex[1] = (Double_t)v->GetYv();
352 vertex[2] = (Double_t)v->GetZv();
355 const AliESDVertex *v = esd->GetPrimaryVertexTPC();
357 // get primary vertex
358 vertex[0] = (Double_t)v->GetXv();
359 vertex[1] = (Double_t)v->GetYv();
360 vertex[2] = (Double_t)v->GetZv();
362 rsn->SetPrimaryVertex(vertex[0], vertex[1], vertex[2]);
364 // store tracks from ESD
365 Float_t p[2], cov[3];
366 Int_t index, label, labmum;
369 AliESDtrack *esdTrack = 0x0, esdTrackTmp;
370 for (index = 0; index < ntracks; index++) {
371 // skip track recognized as the worse one in a splitted pair
372 if (!accept[index]) {
373 AliDebug(10, Form("Rejecting split track #%d in this event", index));
377 esdTrack = esd->GetTrack(index);
378 // check for ESD track cuts (if required)
379 if (fUseESDTrackCuts && (!fESDTrackCuts.AcceptTrack(esdTrack))) continue;
380 // check for fake tracks
381 label = esdTrack->GetLabel();
382 if (fRejectFakes && (label < 0)) continue;
383 // check for minimum number of clusters in ITS, TPC and TRD
384 if (fITSClusters > 0 && (esdTrack->GetITSclusters(0x0) < fITSClusters)) if (!fTPCOnly) continue;
385 if (fTPCClusters > 0 && (esdTrack->GetTPCclusters(0x0) < fTPCClusters)) continue;
386 if (fTRDClusters > 0 && (esdTrack->GetTRDclusters(0x0) < fTRDClusters)) if (!fTPCOnly) continue;
387 // switch to TPC data if required
389 esdTrack->GetImpactParametersTPC(p, cov);
390 if (p[0] == 0. && p[1] == 0.) {
391 esdTrack->RelateToVertexTPC(esd->GetPrimaryVertexTPC(), esd->GetMagneticField(), kVeryBig);
393 check = esdTrack->FillTPCOnlyTrack(esdTrackTmp);
394 if (check) esdTrack = &esdTrackTmp; else continue;
396 // try to get information from this track
397 // output value tells if this was successful or not
398 check = ConvertTrack(&temp, esdTrack);
400 AliDebug(10, Form("Failed adopting track #%d", index));
404 // if stack is present, copy MC info
406 TParticle *part = stack->Particle(TMath::Abs(label));
408 temp.InitMCInfo(part);
409 labmum = part->GetFirstMother();
411 TParticle *mum = stack->Particle(labmum);
412 temp.GetMCInfo()->SetMotherPDG(mum->GetPdgCode());
417 // set index and label
418 temp.SetIndex(index);
419 temp.SetLabel(label);
421 // check this object against the Rsn cuts (if required)
422 if (fUseRsnTrackCuts) {
423 if (!fRsnTrackCuts.IsSelected(AliRsnCut::kParticle, &temp)) continue;
426 // try to add track to collection and returns an error in case of problems
427 AliRsnDaughter *ptr = rsn->AddTrack(temp);
428 if (!ptr) AliWarning(Form("Failed storing track#%d", index));
431 // compute total multiplicity
432 rsn->MakeComputations();
433 if (rsn->GetMultiplicity() <= 0) {
434 AliDebug(1, "Zero Multiplicity in this event");
438 // sort tracks w.r. to Pt (from largest to smallest)
441 // correct tracks for primary vertex
442 //rsn->CorrectTracks();
447 //_____________________________________________________________________________
448 Bool_t AliRsnReader::FillFromAOD(AliRsnEvent *rsn, AliAODEvent *aod, AliMCEvent *mc)
451 // Filler from an AOD event.
452 // Stores all tracks (if a filter is defined, it will store
453 // only the ones which survive the cuts).
454 // If a reference MC event is provided, it is used to store
455 // the MC informations for each track (true PDG code,
456 // GEANT label of mother, PDG code of mother, if any).
457 // When this is used, the 'source' flag of the output
458 // AliRsnEvent object will be set to 'kAOD'.
461 // retrieve stack (if possible)
462 AliStack *stack = 0x0;
463 if (mc) stack = mc->Stack();
465 // get number of tracks
466 Int_t ntracks = aod->GetNTracks();
467 if (!ntracks) return kFALSE;
469 // get primary vertex
471 vertex[0] = aod->GetPrimaryVertex()->GetX();
472 vertex[1] = aod->GetPrimaryVertex()->GetY();
473 vertex[2] = aod->GetPrimaryVertex()->GetZ();
474 rsn->SetPrimaryVertex(vertex[0], vertex[1], vertex[2]);
476 // set MC primary vertex if present
478 Double_t mcvx = 0., mcvy = 0., mcvz = 0.;
480 mc->GenEventHeader()->PrimaryVertex(fvertex);
481 mcvx = (Double_t)fvertex[0];
482 mcvy = (Double_t)fvertex[1];
483 mcvz = (Double_t)fvertex[2];
484 rsn->SetPrimaryVertexMC(mcvx, mcvy, mcvz);
487 // store tracks from ESD
488 Int_t index, label, labmum;
490 AliAODTrack *aodTrack = 0;
492 TObjArrayIter iter(aod->GetTracks());
493 while ((aodTrack = (AliAODTrack*)iter.Next()))
496 index = aod->GetTracks()->IndexOf(aodTrack);
497 label = aodTrack->GetLabel();
498 if (fRejectFakes && (label < 0)) continue;
499 // copy ESD track data into RsnDaughter
500 // if unsuccessful, this track is skipped
501 check = ConvertTrack(&temp, aodTrack);
502 if (!check) continue;
503 // if stack is present, copy MC info
506 TParticle *part = stack->Particle(TMath::Abs(label));
509 temp.InitMCInfo(part);
510 labmum = part->GetFirstMother();
513 TParticle *mum = stack->Particle(labmum);
514 temp.GetMCInfo()->SetMotherPDG(mum->GetPdgCode());
518 // set index and label and add this object to the output container
519 temp.SetIndex(index);
520 temp.SetLabel(label);
522 // check this object against the Rsn cuts (if required)
523 if (fUseRsnTrackCuts) {
524 if (!fRsnTrackCuts.IsSelected(AliRsnCut::kParticle, &temp)) continue;
527 AliRsnDaughter *ptr = rsn->AddTrack(temp);
528 // if problems occurred while storin, that pointer is NULL
529 if (!ptr) AliWarning(Form("Failed storing track#%d"));
532 // compute total multiplicity
533 rsn->MakeComputations();
534 if (rsn->GetMultiplicity() <= 0)
536 AliDebug(1, "Zero multiplicity in this event");
540 // correct tracks for primary vertex
541 rsn->CorrectTracks();
546 //_____________________________________________________________________________
547 Bool_t AliRsnReader::FillFromMC(AliRsnEvent *rsn, AliMCEvent *mc)
550 // Filler from an ESD event.
551 // Stores all tracks which generate at least one
552 // TrackReference (a point in a sensitive volume).
553 // In this case, the MC info is stored by default and
554 // perfect particle identification is the unique available.
555 // When this is used, the 'source' flag of the output
556 // AliRsnEvent object will be set to 'kMC'.
559 // get number of tracks
560 Int_t ntracks = mc->GetNumberOfTracks();
561 if (!ntracks) return kFALSE;
563 AliStack *stack = mc->Stack();
565 // get primary vertex
568 mc->GenEventHeader()->PrimaryVertex(fvertex);
569 vx = (Double_t)fvertex[0];
570 vy = (Double_t)fvertex[1];
571 vz = (Double_t)fvertex[2];
572 rsn->SetPrimaryVertex(vx, vy, vz);
573 rsn->SetPrimaryVertexMC(vx, vy, vz);
575 // store tracks from MC
576 Int_t i, index, labmum, nRef, nRefITS, nRefTPC, detectorID;
578 for (index = 0; index < ntracks; index++)
580 // get MC track & take index and label
581 AliMCParticle *mcTrack = mc->GetTrack(index);
582 temp.SetIndex(index);
583 temp.SetLabel(mcTrack->Label());
585 // check particle track references
586 nRef = mcTrack->GetNumberOfTrackReferences();
587 for (i = 0, nRefITS = 0, nRefTPC = 0; i < nRef; i++) {
588 AliTrackReference *trackRef = mcTrack->GetTrackReference(i);
589 if (!trackRef) continue;
590 detectorID = trackRef->DetectorId();
591 switch (detectorID) {
592 case AliTrackReference::kITS : nRefITS++; break;
593 case AliTrackReference::kTPC : nRefTPC++; break;
597 if (fTrackRefs > 0 && nRef < fTrackRefs) continue;
598 if (fTrackRefsITS > 0 && nRefITS < fTrackRefsITS) continue;
599 if (fTrackRefsTPC > 0 && nRefTPC < fTrackRefsTPC) continue;
601 // try to insert in the RsnDaughter its data
602 TParticle *mcPart = mcTrack->Particle();
603 if (!ConvertTrack(&temp, mcPart)) continue;
605 // assign mother label and PDG code (if any)
606 labmum = temp.GetMCInfo()->Mother();
608 TParticle *mum = stack->Particle(labmum);
609 temp.GetMCInfo()->SetMotherPDG(mum->GetPdgCode());
612 // check this object against the Rsn cuts (if required)
613 if (fUseRsnTrackCuts) {
614 if (!fRsnTrackCuts.IsSelected(AliRsnCut::kParticle, &temp)) continue;
617 AliRsnDaughter *ptr = rsn->AddTrack(temp);
618 if (!ptr) AliWarning(Form("Failed storing track #%d", index));
621 // compute total multiplicity
622 rsn->MakeComputations();
623 if (rsn->GetMultiplicity() <= 0)
625 AliDebug(1, "Zero multiplicity in this event");
629 // sort tracks w.r. to Pt (from largest to smallest)
632 // correct tracks for primary vertex
633 rsn->CorrectTracks();