]>
Commit | Line | Data |
---|---|---|
1 | // | |
2 | // Class AliRsnDaughter | |
3 | // | |
4 | // Interface to candidate daughters of a resonance (tracks). | |
5 | // Points to the source of information, which is generally an AliVParticle-derived object | |
6 | // and contains few internal data-members to store "on fly" some important information | |
7 | // for the computations required during resonance analysis. | |
8 | // --- | |
9 | // Since the package revision, this object is not supposed to be stacked in memory | |
10 | // but created "on fly" during analysis and used just for computations, as an interface. | |
11 | // | |
12 | // authors: A. Pulvirenti (alberto.pulvirenti@ct.infn.it) | |
13 | // M. Vala (martin.vala@cern.ch) | |
14 | // | |
15 | ||
16 | #include <Riostream.h> | |
17 | #include <TParticle.h> | |
18 | ||
19 | #include "AliStack.h" | |
20 | #include "AliESDtrack.h" | |
21 | #include "AliAODEvent.h" | |
22 | #include "AliAODVertex.h" | |
23 | #include "AliAODTrack.h" | |
24 | ||
25 | #include "AliRsnPIDDefESD.h" | |
26 | #include "AliRsnDaughter.h" | |
27 | ||
28 | ClassImp(AliRsnDaughter) | |
29 | ||
30 | AliRsnDaughter::EPIDMethod AliRsnDaughter::fgPIDMethod = AliRsnDaughter::kRealistic; | |
31 | ||
32 | //_____________________________________________________________________________ | |
33 | AliRsnDaughter::AliRsnDaughter(AliVParticle *ref, TParticle *refMC) : | |
34 | fOK((ref != 0)), | |
35 | fKinkIndex(0), | |
36 | fParticle(refMC), | |
37 | fMotherPDG(0), | |
38 | fStatus(0), | |
39 | fPairIndex(0), | |
40 | fDr(0.0), | |
41 | fDz(0.0), | |
42 | fReqPID(AliPID::kUnknown), | |
43 | fRef(ref) | |
44 | { | |
45 | // | |
46 | // Default constructor. | |
47 | // | |
48 | } | |
49 | ||
50 | //_____________________________________________________________________________ | |
51 | AliRsnDaughter::AliRsnDaughter(const AliRsnDaughter ©) : | |
52 | TObject(copy), | |
53 | fOK(copy.fOK), | |
54 | fKinkIndex(copy.fKinkIndex), | |
55 | fParticle(copy.fParticle), | |
56 | fMotherPDG(copy.fMotherPDG), | |
57 | fStatus(copy.fStatus), | |
58 | fPairIndex(copy.fPairIndex), | |
59 | fDr(copy.fDr), | |
60 | fDz(copy.fDz), | |
61 | fReqPID(copy.fReqPID), | |
62 | fRef(copy.fRef) | |
63 | { | |
64 | // | |
65 | // Copy constructor. | |
66 | // Pointers are NOT duplicated. | |
67 | // | |
68 | } | |
69 | ||
70 | //_____________________________________________________________________________ | |
71 | AliRsnDaughter& AliRsnDaughter::operator=(const AliRsnDaughter ©) | |
72 | { | |
73 | // | |
74 | // Assignment operator. | |
75 | // | |
76 | ||
77 | (TObject)(*this) = (TObject)copy; | |
78 | ||
79 | fOK = copy.fOK; | |
80 | fKinkIndex = copy.fKinkIndex; | |
81 | fParticle = copy.fParticle; | |
82 | fMotherPDG = copy.fMotherPDG; | |
83 | fStatus = copy.fStatus; | |
84 | fPairIndex = copy.fPairIndex; | |
85 | fDr = copy.fDr; | |
86 | fDz = copy.fDz; | |
87 | ||
88 | fReqPID = copy.fReqPID; | |
89 | ||
90 | fRef = copy.fRef; | |
91 | ||
92 | return (*this); | |
93 | } | |
94 | ||
95 | //_____________________________________________________________________________ | |
96 | AliRsnDaughter::~AliRsnDaughter() | |
97 | { | |
98 | // | |
99 | // Destructor. | |
100 | // Since pointers do not allocate new objects, nothing is done. | |
101 | // | |
102 | } | |
103 | ||
104 | //_____________________________________________________________________________ | |
105 | void AliRsnDaughter::RotateP | |
106 | (Double_t angle, Double_t &x, Double_t &y, Bool_t isDegrees) const | |
107 | { | |
108 | // | |
109 | // Rotate the transverse momentum by an angle (in DEGREES) | |
110 | // around Z axis (does not change the Z component). | |
111 | // Rotated values are stored in the two arguments passed by reference. | |
112 | // | |
113 | ||
114 | if (isDegrees) angle *= TMath::DegToRad(); | |
115 | ||
116 | Double_t s = TMath::Sin(angle); | |
117 | Double_t c = TMath::Cos(angle); | |
118 | ||
119 | x = c*Px() - s*Py(); | |
120 | y = s*Px() + c*Py(); | |
121 | } | |
122 | ||
123 | //_____________________________________________________________________________ | |
124 | Double_t AliRsnDaughter::AngleTo(AliRsnDaughter d, Bool_t outInDegrees) | |
125 | { | |
126 | // | |
127 | // Compute angle between the vector momentum of this | |
128 | // and the one of argument. | |
129 | // | |
130 | ||
131 | Double_t arg, dot, ptot2 = P2() * d.P2(); | |
132 | ||
133 | if (ptot2 <= 0) { | |
134 | return 0.0; | |
135 | } else { | |
136 | dot = Px()*d.Px() + Py()*d.Py() + Pz()*d.Pz(); | |
137 | arg = dot / TMath::Sqrt(ptot2); | |
138 | if (arg > 1.0) arg = 1.0; | |
139 | if (arg < -1.0) arg = -1.0; | |
140 | if (outInDegrees) return TMath::ACos(arg) * TMath::RadToDeg(); | |
141 | else return TMath::ACos(arg); | |
142 | } | |
143 | } | |
144 | ||
145 | //_____________________________________________________________________________ | |
146 | Int_t AliRsnDaughter::GetID() const | |
147 | { | |
148 | // | |
149 | // Return reference index, using the "GetID" method | |
150 | // of the possible source object. | |
151 | // | |
152 | ||
153 | AliESDtrack *esd = dynamic_cast<AliESDtrack*>(fRef); | |
154 | if (esd) return esd->GetID(); | |
155 | ||
156 | AliAODTrack *aod = dynamic_cast<AliAODTrack*>(fRef); | |
157 | if (aod) return aod->GetID(); | |
158 | ||
159 | return GetLabel(); | |
160 | } | |
161 | ||
162 | //_____________________________________________________________________________ | |
163 | AliPID::EParticleType AliRsnDaughter::RealisticPID() const | |
164 | { | |
165 | // | |
166 | // Return the "realistic" PID of this track, | |
167 | // i.e. the particle species to which corresponds the largest PID probability. | |
168 | // | |
169 | ||
170 | AliPID::EParticleType pid = AliPID::kElectron; | |
171 | Double_t prob = fPID[0]; | |
172 | ||
173 | Int_t i; | |
174 | for (i = 1; i < AliPID::kSPECIES; i++) { | |
175 | if (fPID[i] > prob) { | |
176 | prob = fPID[i]; | |
177 | pid = (AliPID::EParticleType)i; | |
178 | } | |
179 | } | |
180 | ||
181 | return pid; | |
182 | } | |
183 | ||
184 | //_____________________________________________________________________________ | |
185 | AliPID::EParticleType AliRsnDaughter::PerfectPID() const | |
186 | { | |
187 | // | |
188 | // Return the "perfect" PID of this track, | |
189 | // reading it from the MC information, if available. | |
190 | // | |
191 | ||
192 | if (!fParticle) return AliPID::kUnknown; | |
193 | ||
194 | Int_t absPDG = TMath::Abs(fParticle->GetPdgCode()); | |
195 | switch (absPDG) { | |
196 | case 11: | |
197 | return AliPID::kElectron; | |
198 | case 13: | |
199 | return AliPID::kMuon; | |
200 | case 211: | |
201 | return AliPID::kPion; | |
202 | case 321: | |
203 | return AliPID::kKaon; | |
204 | case 2212: | |
205 | return AliPID::kProton; | |
206 | default: | |
207 | AliDebug(2, Form("PDG code = %d not recognized. Return 'AliPID::kUnknown'", absPDG)); | |
208 | return AliPID::kUnknown; | |
209 | } | |
210 | } | |
211 | ||
212 | //_____________________________________________________________________________ | |
213 | AliPID::EParticleType AliRsnDaughter::PIDType(Double_t &prob) const | |
214 | { | |
215 | // | |
216 | // Return the PID type according to the selected method | |
217 | // in the argument passed by reference, the probability is stored. | |
218 | // It will be realistic for realistic PID and 1 for perfect PID. | |
219 | // | |
220 | ||
221 | AliPID::EParticleType pid = AssignedPID(); | |
222 | ||
223 | prob = 1.0; | |
224 | if (fgPIDMethod == kRealistic) prob = fPID[(Int_t)pid]; | |
225 | ||
226 | return pid; | |
227 | } | |
228 | ||
229 | //_____________________________________________________________________________ | |
230 | AliPID::EParticleType AliRsnDaughter::AssignedPID() const | |
231 | { | |
232 | // | |
233 | // Return the PID type according to the selected method | |
234 | // in the argument passed by reference, the probability is stored. | |
235 | // It will be realistic for realistic PID and 1 for perfect PID. | |
236 | // | |
237 | ||
238 | switch (fgPIDMethod) { | |
239 | case kNoPID: | |
240 | return AliPID::kUnknown; | |
241 | case kPerfect: | |
242 | return PerfectPID(); | |
243 | case kRealistic: | |
244 | return RealisticPID(); | |
245 | default: | |
246 | AliWarning("PID method not properly set. Returning realistic PID"); | |
247 | return RealisticPID(); | |
248 | } | |
249 | } | |
250 | ||
251 | //_____________________________________________________________________________ | |
252 | Bool_t AliRsnDaughter::CombineWithPriors(const Double_t *priors, AliRsnPIDDefESD *pidDef) | |
253 | { | |
254 | // | |
255 | // Combine current PID weights (assumed to be them) with prior probs | |
256 | // | |
257 | ||
258 | Int_t i; | |
259 | Double_t sum = 0.0; | |
260 | ||
261 | // get PID weights according to definition | |
262 | // if the reference is not ESD or the pidDef is null | |
263 | // of it is not null but is requires the ESD pid, | |
264 | // the standard PID value is used, otherwise | |
265 | if (pidDef && GetRefESD()) { | |
266 | pidDef->ComputeWeights(GetRefESD(), fPID); | |
267 | } else { | |
268 | if (fRef->PID()) | |
269 | for (i = 0; i < AliPID::kSPECIES; i++) fPID[i] = fRef->PID()[i]; | |
270 | else if (fParticle) { | |
271 | // if the PID() returns 0x0, this is a MC particle | |
272 | // and we set the weight corresponding to its species to 1 | |
273 | // and the others to zero | |
274 | for (i = 0; i < AliPID::kSPECIES; i++) fPID[i] = 0.0; | |
275 | i = (Int_t)AliRsnDaughter::InternalType(TMath::Abs(fParticle->GetPdgCode())); | |
276 | fPID[i] = 1.0; | |
277 | } | |
278 | } | |
279 | ||
280 | // multiply weights and priors | |
281 | for (i = 0; i < AliPID::kSPECIES; i++) { | |
282 | fPID[i] *= priors[i]; | |
283 | sum += fPID[i]; | |
284 | } | |
285 | if (sum <= 0.0) { | |
286 | if (sum < 0.0) AliError(Form("Sum of weights = %f < 0", sum)); | |
287 | return kFALSE; | |
288 | } | |
289 | ||
290 | // normalize | |
291 | for (i = 0; i < AliPID::kSPECIES; i++) fPID[i] /= sum; | |
292 | ||
293 | return kTRUE; | |
294 | } | |
295 | ||
296 | //_____________________________________________________________________________ | |
297 | void AliRsnDaughter::FindMotherPDG(AliStack *const stack) | |
298 | { | |
299 | // | |
300 | // Searches the stack to find the mother and retrieve its PDG code. | |
301 | // | |
302 | ||
303 | if (!stack || !fParticle) return; | |
304 | ||
305 | const Int_t mLabel = fParticle->GetFirstMother(); | |
306 | if (mLabel < 0) { | |
307 | fMotherPDG = 0; | |
308 | } else { | |
309 | TParticle *mum = stack->Particle(mLabel); | |
310 | if (mum) fMotherPDG = mum->GetPdgCode(); | |
311 | else fMotherPDG = 0; | |
312 | } | |
313 | } | |
314 | ||
315 | //_____________________________________________________________________________ | |
316 | Double_t AliRsnDaughter::GetMCEnergy(Double_t mass) | |
317 | { | |
318 | // | |
319 | // Uses the argument to compute 4-momentum energy | |
320 | // | |
321 | ||
322 | if (!fParticle) return 0.0; | |
323 | ||
324 | Double_t p2 = fParticle->Px()*fParticle->Px(); | |
325 | p2 += fParticle->Py()*fParticle->Py(); | |
326 | p2 += fParticle->Pz()*fParticle->Pz(); | |
327 | ||
328 | return TMath::Sqrt(mass*mass + p2); | |
329 | } | |
330 | ||
331 | //_____________________________________________________________________________ | |
332 | void AliRsnDaughter::FindKinkIndex(const AliESDtrack *esdTrack) | |
333 | { | |
334 | // | |
335 | // Assign kink index from an ESD track | |
336 | // | |
337 | ||
338 | Int_t i, ik[3]; | |
339 | for (i = 0; i < 3; i++) ik[i] = esdTrack->GetKinkIndex(i); | |
340 | ||
341 | if (ik[0] < 0 || ik[1] < 0 || ik[2] < 0) { | |
342 | SetKinkMother(); | |
343 | } else if (ik[0] > 0 || ik[1] > 0 || ik[2] > 0) { | |
344 | SetKinkDaughter(); | |
345 | } else SetNoKink(); | |
346 | } | |
347 | ||
348 | //_____________________________________________________________________________ | |
349 | void AliRsnDaughter::FindKinkIndex(AliAODEvent *const event) | |
350 | { | |
351 | // | |
352 | // Assign kink index from an AOD event | |
353 | // | |
354 | ||
355 | Int_t iv, id, nD, nV = event->GetNumberOfVertices(); | |
356 | for (iv = 0; iv < nV; iv++) { | |
357 | AliAODVertex *v = event->GetVertex(iv); | |
358 | AliAODVertex::AODVtx_t type = (AliAODVertex::AODVtx_t)v->GetType(); | |
359 | if (type != AliAODVertex::kKink) continue; | |
360 | AliAODTrack *mother = (AliAODTrack*)v->GetParent(); | |
361 | if (mother == (AliAODTrack*)fRef) { | |
362 | SetKinkMother(); | |
363 | return; | |
364 | } else { | |
365 | nD = v->GetNDaughters(); | |
366 | for (id = 0; id < nD; id++) { | |
367 | AliAODTrack *son = (AliAODTrack*)v->GetDaughter(id); | |
368 | if (son == (AliAODTrack*)fRef) { | |
369 | SetKinkDaughter(); | |
370 | return; | |
371 | } | |
372 | } | |
373 | } | |
374 | } | |
375 | ||
376 | SetNoKink(); | |
377 | } | |
378 | ||
379 | //_____________________________________________________________________________ | |
380 | void AliRsnDaughter::Reset() | |
381 | { | |
382 | // | |
383 | // Reset this track to meaningless values | |
384 | // | |
385 | ||
386 | fOK = kFALSE; | |
387 | fKinkIndex = 0; | |
388 | fParticle = 0x0; | |
389 | fMotherPDG = 0; | |
390 | fStatus = 0; | |
391 | fRef = 0x0; | |
392 | } | |
393 | ||
394 | //_____________________________________________________________________________ | |
395 | void AliRsnDaughter::Print(Option_t * const option) const | |
396 | { | |
397 | // | |
398 | // Prints the values of data members, using the options: | |
399 | // - P --> momentum | |
400 | // - V --> DCA vertex | |
401 | // - C --> electric charge | |
402 | // - F --> flags | |
403 | // - I --> identification (PID, probability and mass) | |
404 | // - W --> PID weights | |
405 | // - M --> Montecarlo | |
406 | // - L --> index & label | |
407 | // - A --> angles | |
408 | // - ALL --> All oprions switched on | |
409 | // | |
410 | // Index and label are printed by default. | |
411 | // | |
412 | ||
413 | TString opt(option); | |
414 | opt.ToUpper(); | |
415 | ||
416 | if (opt.Contains("L") || opt.Contains("ALL")) { | |
417 | cout << ".......Index : " << GetID() << endl; | |
418 | cout << ".......Label : " << GetLabel() << endl; | |
419 | } | |
420 | if (opt.Contains("P") || opt.Contains("ALL")) { | |
421 | cout << ".......Px, Py, Pz, Pt : " << Px() << ' ' << Py() << ' ' << Pz() << ' ' << Pt() << endl; | |
422 | } | |
423 | if (opt.Contains("A") || opt.Contains("ALL")) { | |
424 | cout << ".......Phi, Theta : " << Phi() << ' ' << Theta() << endl; | |
425 | } | |
426 | if (opt.Contains("V") || opt.Contains("ALL")) { | |
427 | cout << ".......Vx, Vy, Vz : " << Xv() << ' ' << Yv() << ' ' << Zv() << endl; | |
428 | } | |
429 | if (opt.Contains("I") || opt.Contains("ALL")) { | |
430 | AliPID::EParticleType type; | |
431 | Double_t prob; | |
432 | type = PIDType(prob); | |
433 | cout << ".......PID & prob : " << AliPID::ParticleName(type) << ' ' << prob << endl; | |
434 | } | |
435 | if (opt.Contains("C") || opt.Contains("ALL")) { | |
436 | cout << ".......Charge : " << Charge() << endl; | |
437 | } | |
438 | if (opt.Contains("F") || opt.Contains("ALL")) { | |
439 | cout << ".......Flags : " << fStatus << endl; | |
440 | } | |
441 | if (opt.Contains("W") || opt.Contains("ALL")) { | |
442 | cout << ".......Weights : "; | |
443 | Int_t i; | |
444 | for (i = 0; i < AliPID::kSPECIES; i++) cout << fPID[i] << ' '; | |
445 | cout << endl; | |
446 | } | |
447 | if (opt.Contains("M") || opt.Contains("ALL")) { | |
448 | if (fParticle) { | |
449 | cout << ".......PDG code : " << fParticle->GetPdgCode() << endl; | |
450 | cout << ".......Mother (label) : " << fParticle->GetFirstMother() << endl; | |
451 | cout << ".......Mother (PDG code): " << fMotherPDG << endl; | |
452 | } else { | |
453 | cout << ".......MC info not present" << endl; | |
454 | } | |
455 | } | |
456 | } | |
457 | ||
458 | //_____________________________________________________________________________ | |
459 | AliPID::EParticleType AliRsnDaughter::InternalType(Int_t pdg) | |
460 | { | |
461 | // | |
462 | // Return the internal enum value corresponding to the PDG | |
463 | // code passed as argument, if possible. | |
464 | // Otherwise, returns 'AliPID::kSPECIES' by default. | |
465 | // | |
466 | ||
467 | AliPID::EParticleType value; | |
468 | Int_t absPDG = TMath::Abs(pdg); | |
469 | ||
470 | switch (absPDG) { | |
471 | case 11: | |
472 | value = AliPID::kElectron; | |
473 | break; | |
474 | case 13: | |
475 | value = AliPID::kMuon; | |
476 | break; | |
477 | case 211: | |
478 | value = AliPID::kPion; | |
479 | break; | |
480 | case 321: | |
481 | value = AliPID::kKaon; | |
482 | break; | |
483 | case 2212: | |
484 | value = AliPID::kProton; | |
485 | break; | |
486 | default: | |
487 | value = AliPID::kUnknown; | |
488 | } | |
489 | return value; | |
490 | } | |
491 | ||
492 | //_____________________________________________________________________________ | |
493 | const char* AliRsnDaughter::MethodName(EPIDMethod method) | |
494 | { | |
495 | // | |
496 | // Returns a string with the method name | |
497 | // | |
498 | ||
499 | switch (method) | |
500 | { | |
501 | case kNoPID: | |
502 | return "No PID"; | |
503 | case kRealistic: | |
504 | return "Realistic"; | |
505 | case kPerfect: | |
506 | return "Perfect"; | |
507 | default: | |
508 | return "Unknown"; | |
509 | } | |
510 | } |