1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15 /**************************************************************************
17 * QA class of Heavy Flavor quark and fragmeted/decayed particles *
18 * -Check kinematics of Heavy Quarks/hadrons, and decayed leptons *
20 * decay lepton kinematics w/wo acceptance *
21 * heavy hadron decay length, electron pT fraction carried from decay *
22 * -Check yield of Heavy Quarks/hadrons *
23 * Number of produced heavy quark *
24 * Number of produced hadron of given pdg code *
28 * MinJung Kweon <minjung@physi.uni-heidelberg.de> *
30 **************************************************************************/
41 #include <TDatabasePDG.h>
43 #include <TParticle.h>
46 #include <AliESDEvent.h>
47 #include <AliESDtrack.h>
48 #include <AliESDInputHandler.h>
49 #include <AliESDVertex.h>
52 #include "AliHFEmcQA.h"
54 const Int_t AliHFEmcQA::fgkGluon=21;
55 const Int_t AliHFEmcQA::fgkMaxGener=10;
56 const Int_t AliHFEmcQA::fgkMaxIter=100;
57 const Int_t AliHFEmcQA::fgkqType = 7; // number of species waiting for QA done
61 //_______________________________________________________________________________________________
62 AliHFEmcQA::AliHFEmcQA() :
66 // Default constructor
70 //_______________________________________________________________________________________________
71 AliHFEmcQA::AliHFEmcQA(const AliHFEmcQA&p):
74 ,fNparents(p.fNparents)
79 //_______________________________________________________________________________________________
81 AliHFEmcQA::operator=(const AliHFEmcQA &)
83 // Assignment operator
85 AliInfo("Not yet implemented.");
89 //_______________________________________________________________________________________________
90 AliHFEmcQA::~AliHFEmcQA()
94 AliInfo("Analysis Done.");
97 //_______________________________________________________________________________________________
98 void AliHFEmcQA::PostAnalyze()
102 //__________________________________________
103 void AliHFEmcQA::CreateHistograms(const Int_t kquark, Int_t icut, TString hnopt)
107 if (kquark != kCharm && kquark != kBeauty) {
108 AliDebug(1, "This task is only for heavy quark QA, return\n");
111 Int_t iq = kquark - kCharm;
113 TString kqTypeLabel[fgkqType];
114 if (kquark == kCharm){
115 kqTypeLabel[kQuark]="c";
116 kqTypeLabel[kantiQuark]="cbar";
117 kqTypeLabel[kHadron]="cHadron";
118 kqTypeLabel[keHadron]="ceHadron";
119 kqTypeLabel[kDeHadron]="nullHadron";
120 kqTypeLabel[kElectron]="ce";
121 kqTypeLabel[kElectron2nd]="nulle";
122 } else if (kquark == kBeauty){
123 kqTypeLabel[kQuark]="b";
124 kqTypeLabel[kantiQuark]="bbar";
125 kqTypeLabel[kHadron]="bHadron";
126 kqTypeLabel[keHadron]="beHadron";
127 kqTypeLabel[kDeHadron]="bDeHadron";
128 kqTypeLabel[kElectron]="be";
129 kqTypeLabel[kElectron2nd]="bce";
134 for (Int_t iqType = 0; iqType < fgkqType; iqType++ ){
135 if (iqType < keHadron && icut > 0) continue; // don't duplicate histogram for quark and hadron
136 hname = hnopt+"PdgCode_"+kqTypeLabel[iqType];
137 fHist[iq][iqType][icut].fPdgCode = new TH1F(hname,hname,20001,-10000.5,10000.5);
138 hname = hnopt+"Pt_"+kqTypeLabel[iqType];
139 fHist[iq][iqType][icut].fPt = new TH1F(hname,hname+";p_{T} (GeV/c)",250,0,50);
140 hname = hnopt+"Y_"+kqTypeLabel[iqType];
141 fHist[iq][iqType][icut].fY = new TH1F(hname,hname,150,-7.5,7.5);
142 hname = hnopt+"Eta_"+kqTypeLabel[iqType];
143 fHist[iq][iqType][icut].fEta = new TH1F(hname,hname,150,-7.5,7.5);
147 hname = hnopt+"Nq_"+kqTypeLabel[kQuark];
148 fHistComm[iq][icut].fNq = new TH1F(hname,hname,10,-0.5,9.5);
149 hname = hnopt+"ProcessID_"+kqTypeLabel[kQuark];
150 fHistComm[iq][icut].fProcessID = new TH1F(hname,hname,21,-10.5,10.5);
152 hname = hnopt+"ePtRatio_"+kqTypeLabel[kQuark];
153 fHistComm[iq][icut].fePtRatio = new TH2F(hname,hname+";p_{T} (GeV/c);momentum fraction",100,0,30,100,0,1);
154 hname = hnopt+"DePtRatio_"+kqTypeLabel[kQuark];
155 fHistComm[iq][icut].fDePtRatio = new TH2F(hname,hname+";p_{T} (GeV/c);momentum fraction",100,0,30,100,0,1);
156 hname = hnopt+"eDistance_"+kqTypeLabel[kQuark];
157 fHistComm[iq][icut].feDistance= new TH2F(hname,hname+";p_{T} (GeV/c);distance (cm)",100,0,30,200,0,2);
158 hname = hnopt+"DeDistance_"+kqTypeLabel[kQuark];
159 fHistComm[iq][icut].fDeDistance= new TH2F(hname,hname+";p_{T} (GeV/c);distance (cm)",100,0,30,200,0,2);
163 //__________________________________________
164 void AliHFEmcQA::Init()
166 // called at begining every event
168 for (Int_t i=0; i<2; i++){
174 fParentSelect[0][0] = 411;
175 fParentSelect[0][1] = 421;
176 fParentSelect[0][2] = 431;
177 fParentSelect[0][3] = 4122;
178 fParentSelect[0][4] = 4132;
179 fParentSelect[0][5] = 4232;
180 fParentSelect[0][6] = 4332;
182 fParentSelect[1][0] = 511;
183 fParentSelect[1][1] = 521;
184 fParentSelect[1][2] = 531;
185 fParentSelect[1][3] = 5122;
186 fParentSelect[1][4] = 5132;
187 fParentSelect[1][5] = 5232;
188 fParentSelect[1][6] = 5332;
192 //__________________________________________
193 void AliHFEmcQA::GetQuarkKine(Int_t iTrack, const Int_t kquark)
195 // get heavy quark kinematics
197 if (kquark != kCharm && kquark != kBeauty) {
198 AliDebug(1, "This task is only for heavy quark QA, return\n");
201 Int_t iq = kquark - kCharm;
205 AliDebug(1, "Stack label is negative, return\n");
209 TParticle *part = fStack->Particle(iTrack);
210 Int_t partPdgcode = TMath::Abs(part->GetPdgCode());
212 // select heavy hadron or not fragmented heavy quark
213 if ( int(partPdgcode/100.)==kquark || int(partPdgcode/1000.)==kquark || (partPdgcode==kquark && (part->GetNDaughters()==0 && iTrack>5)) ){
215 TParticle *partMother;
218 if (partPdgcode == kquark){ // in case of not fragmented heavy quark
221 } else{ // in case of heavy hadron, start to search for mother heavy parton
222 iLabel = part->GetFirstMother();
223 if (iLabel>-1) { partMother = fStack->Particle(iLabel); }
225 AliDebug(1, "Stack label is negative, return\n");
230 // heavy parton selection as a mother of heavy hadron
231 // if the heavy particle comes from string which is denoted as particle status 12|12|12...12|11,[PYTHIA p.60]
232 // in this case, the mother of heavy particle can be one of the fragmented parton of the string
233 // should I make a condition that partMother should be quark or diquark? -> not necessary
234 if ( abs(partMother->GetPdgCode()) == kquark || (partMother->GetStatusCode() == 11) ){
235 //if ( abs(partMother->GetPdgCode()) == kquark || (partMother->GetStatusCode() == 11 || partMother->GetStatusCode() == 12) ){
237 if ( abs(partMother->GetPdgCode()) != kquark ){
238 // search fragmented partons in the same string
239 Bool_t isSameString = kTRUE;
240 for (Int_t i=1; i<fgkMaxIter; i++){
242 if (iLabel>-1) { partMother = fStack->Particle(iLabel); }
244 AliDebug(1, "Stack label is negative, return\n");
247 if ( abs(partMother->GetPdgCode()) == kquark ) break;
248 if ( partMother->GetStatusCode() != 12 ) isSameString = kFALSE;
249 if (!isSameString) return;
252 AliDebug(1, "Can not find heavy parton of this heavy hadron in the string, return\n");
253 if (abs(partMother->GetPdgCode()) != kquark) return;
255 if (fIsHeavy[iq] >= 50) return;
256 fHeavyQuark[fIsHeavy[iq]] = partMother;
259 // fill kinematics for heavy parton
260 if (partMother->GetPdgCode() > 0) { // quark
261 fHist[iq][kQuark][0].fPdgCode->Fill(partMother->GetPdgCode());
262 fHist[iq][kQuark][0].fPt->Fill(partMother->Pt());
263 fHist[iq][kQuark][0].fY->Fill(GetRapidity(partMother));
264 fHist[iq][kQuark][0].fEta->Fill(partMother->Eta());
266 fHist[iq][kantiQuark][0].fPdgCode->Fill(partMother->GetPdgCode());
267 fHist[iq][kantiQuark][0].fPt->Fill(partMother->Pt());
268 fHist[iq][kantiQuark][0].fY->Fill(GetRapidity(partMother));
269 fHist[iq][kantiQuark][0].fEta->Fill(partMother->Eta());
272 } // end of heavy parton slection loop
274 } // end of heavy hadron or quark selection
278 //__________________________________________
279 void AliHFEmcQA::EndOfEventAna(const Int_t kquark)
281 // end of event analysis
283 if (kquark != kCharm && kquark != kBeauty) {
284 AliDebug(1, "This task is only for heavy quark QA, return\n");
287 Int_t iq = kquark - kCharm;
290 // # of heavy quark per event
291 AliDebug(1,Form("Number of heavy quark in this event = %d \n",fIsHeavy[iq]));
292 fHistComm[iq][0].fNq->Fill(fIsHeavy[iq]);
294 Int_t motherID[fgkMaxGener];
295 Int_t motherType[fgkMaxGener];
296 Int_t motherLabel[fgkMaxGener];
297 Int_t ancestorPdg[fgkMaxGener];
298 Int_t ancestorLabel[fgkMaxGener];
300 for (Int_t i = 0; i < fgkMaxGener; i++){ // initialization
305 ancestorLabel[i] = 0;
308 // check history of found heavy quarks
309 for (Int_t i = 0; i < fIsHeavy[iq]; i++){
311 ancestorLabel[0] = i;
312 ancestorPdg[0] = fHeavyQuark[i]->GetPdgCode();
313 ancestorLabel[1] = fHeavyQuark[i]->GetFirstMother();
315 AliDebug(1,Form("pdg code= %d\n",ancestorPdg[0]));
316 AliDebug(1,Form("ancestor label= %d\n",ancestorLabel[1]));
319 while (ancestorLabel[ig] != -1){
320 // in case there is mother, get mother's pdg code and grandmother's label
321 IdentifyMother(ancestorLabel[ig], ancestorPdg[ig], ancestorLabel[ig+1]);
322 // if mother is still heavy, find again mother's ancestor
323 if (ancestorPdg[ig-1] == ancestorPdg[ig]) {
325 continue; // if it is from same heavy
327 // if the heavy's mother is not heavy, check the mother's label to know if it comes from inital or final parton shower
328 if (IsFromInitialShower(ancestorLabel[ig],motherID[i],motherType[i],motherLabel[i])) break;
329 if (IsFromFinalParton(ancestorLabel[ig],motherID[i],motherType[i],motherLabel[i])) break;
330 // if it is not the above case, something is strange
331 ReportStrangeness(motherID[i],motherType[i],motherLabel[i]);
334 if (ancestorLabel[ig] == -1){ // from hard scattering
335 HardScattering(kquark, motherID[i],motherType[i], motherLabel[i]);
338 } // end of found heavy quark loop
341 // check process type
343 for (Int_t i = 0; i < fIsHeavy[iq]; i++){
344 AliDebug(1,Form("Mother ID= %d type= %d label= %d\n",motherID[i],motherType[i],motherLabel[i]));
348 Int_t nheavypair = Int_t(fIsHeavy[iq]/2.);
349 for (Int_t ipair = 0; ipair < nheavypair; ipair++){
352 Int_t id2 = ipair*2 + 1;
354 if (motherType[id1] == 2 && motherType[id2] == 2){
355 if (motherLabel[id1] == motherLabel[id2]) processID = kGluonSplitting; // gluon spliting
358 else if (motherType[id1] == -1 && motherType[id2] == -1) {
359 if (motherLabel[id1] == -1 && motherLabel[id2] == -1) {
360 if (motherID[id1] == fgkGluon) processID = kPairCreationFromg; // gluon fusion
361 else processID = kPairCreationFromq; // q-qbar pair creation
365 else if (motherType[id1] == -1 || motherType[id2] == -1) {
366 if ((motherLabel[id1] == -1 || motherLabel[id2] == -1) && (motherLabel[id1]*motherLabel[id2] == -2 || motherLabel[id1]*motherLabel[id2] == -3)) {
367 if(motherID[id1]*motherID[id2] == kquark*fgkGluon) processID = kFlavourExitation; // flavour exitation
368 else processID = kLightQuarkShower;
372 else if (motherType[id1] == -2 || motherType[id2] == -2) {
373 if (motherLabel[id1] == motherLabel[id2]) processID = kInitialPartonShower; // initial parton shower
379 if (nheavypair >1) AliDebug(1,Form("Multi pair found : process ID = %d\n",processID));
380 else fHistComm[iq][0].fProcessID->Fill(processID);
381 AliDebug(1,Form("Process ID = %d\n",processID));
382 } // end of # heavy quark pair loop
386 //__________________________________________
387 void AliHFEmcQA::GetHadronKine(Int_t iTrack, const Int_t kquark)
389 // decay electron kinematics
391 if (kquark != kCharm && kquark != kBeauty) {
392 AliDebug(1, "This task is only for heavy quark QA, return\n");
395 Int_t iq = kquark - kCharm;
398 AliDebug(1, "Stack label is negative, return\n");
402 TParticle* mcpart = fStack->Particle(iTrack);
404 Int_t iLabel = mcpart->GetFirstMother();
406 AliDebug(1, "Stack label is negative, return\n");
410 TParticle *partCopy = mcpart;
411 Int_t pdgcode = mcpart->GetPdgCode();
412 Int_t pdgcodeCopy = pdgcode;
414 // if the mother is charmed hadron
415 Bool_t isDirectCharm = kFALSE;
416 if ( int(abs(pdgcode)/100.) == kCharm || int(abs(pdgcode)/1000.) == kCharm ) {
418 // iterate until you find B hadron as a mother or become top ancester
419 for (Int_t i=1; i<fgkMaxIter; i++){
421 Int_t jLabel = mcpart->GetFirstMother();
423 isDirectCharm = kTRUE;
424 break; // if there is no ancester
426 if (jLabel < 0){ // safety protection
427 AliDebug(1, "Stack label is negative, return\n");
430 // if there is an ancester
431 TParticle* mother = fStack->Particle(jLabel);
432 Int_t motherPDG = mother->GetPdgCode();
434 for (Int_t j=0; j<fNparents; j++){
435 if (abs(motherPDG)==fParentSelect[1][j]) return; // return if this hadron is originated from b
439 } // end of iteration
441 if((isDirectCharm == kTRUE && kquark == kCharm) || kquark == kBeauty) {
442 for (Int_t i=0; i<fNparents; i++){
443 if (abs(pdgcodeCopy)==fParentSelect[iq][i]){
445 // fill hadron kinematics
446 fHist[iq][kHadron][0].fPdgCode->Fill(pdgcodeCopy);
447 fHist[iq][kHadron][0].fPt->Fill(partCopy->Pt());
448 fHist[iq][kHadron][0].fY->Fill(GetRapidity(partCopy));
449 fHist[iq][kHadron][0].fEta->Fill(partCopy->Eta());
456 //__________________________________________
457 void AliHFEmcQA::GetDecayedKine(Int_t iTrack, const Int_t kquark, Int_t kdecayed, Int_t icut, Bool_t isbarrel)
459 // decay electron kinematics
461 if (kquark != kCharm && kquark != kBeauty) {
462 AliDebug(1, "This task is only for heavy quark QA, return\n");
465 Int_t iq = kquark - kCharm;
468 AliDebug(1, "Stack label is negative, return\n");
472 TParticle* mcpart = fStack->Particle(iTrack);
474 if ( abs(mcpart->GetPdgCode()) != kdecayed ) return;
475 if ( isbarrel && TMath::Abs(mcpart->Eta()) > 0.9 ) return;
477 Int_t iLabel = mcpart->GetFirstMother();
479 AliDebug(1, "Stack label is negative, return\n");
483 TParticle *partMother = fStack->Particle(iLabel);
484 TParticle *partMotherCopy = partMother;
485 Int_t maPdgcode = partMother->GetPdgCode();
486 Int_t maPdgcodeCopy = maPdgcode;
488 // get electron production vertex
489 TLorentzVector ePoint;
490 mcpart->ProductionVertex(ePoint);
492 // if the mother is charmed hadron
493 Bool_t isMotherDirectCharm = kFALSE;
494 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
496 // iterate until you find B hadron as a mother or become top ancester
497 for (Int_t i=1; i<fgkMaxIter; i++){
499 Int_t jLabel = partMother->GetFirstMother();
501 isMotherDirectCharm = kTRUE;
502 break; // if there is no ancester
504 if (jLabel < 0){ // safety protection
505 AliDebug(1, "Stack label is negative, return\n");
509 // if there is an ancester
510 TParticle* grandMa = fStack->Particle(jLabel);
511 Int_t grandMaPDG = grandMa->GetPdgCode();
513 for (Int_t j=0; j<fNparents; j++){
514 if (abs(grandMaPDG)==fParentSelect[1][j]){
516 if (kquark == kCharm) return;
517 // fill electron kinematics
518 fHist[iq][kElectron2nd][icut].fPdgCode->Fill(mcpart->GetPdgCode());
519 fHist[iq][kElectron2nd][icut].fPt->Fill(mcpart->Pt());
520 fHist[iq][kElectron2nd][icut].fY->Fill(GetRapidity(mcpart));
521 fHist[iq][kElectron2nd][icut].fEta->Fill(mcpart->Eta());
523 // fill mother hadron kinematics
524 fHist[iq][kDeHadron][icut].fPdgCode->Fill(grandMaPDG);
525 fHist[iq][kDeHadron][icut].fPt->Fill(grandMa->Pt());
526 fHist[iq][kDeHadron][icut].fY->Fill(GetRapidity(grandMa));
527 fHist[iq][kDeHadron][icut].fEta->Fill(grandMa->Eta());
529 // ratio between pT of electron and pT of mother B hadron
530 if(grandMa->Pt()) fHistComm[iq][icut].fDePtRatio->Fill(grandMa->Pt(),mcpart->Pt()/grandMa->Pt());
532 // distance between electron production point and mother hadron production point
533 TLorentzVector debPoint;
534 grandMa->ProductionVertex(debPoint);
535 TLorentzVector dedistance = ePoint - debPoint;
536 fHistComm[iq][icut].fDeDistance->Fill(grandMa->Pt(),dedistance.P());
541 partMother = grandMa;
542 } // end of iteration
544 if((isMotherDirectCharm == kTRUE && kquark == kCharm) || kquark == kBeauty) {
545 for (Int_t i=0; i<fNparents; i++){
546 if (abs(maPdgcodeCopy)==fParentSelect[iq][i]){
548 // fill electron kinematics
549 fHist[iq][kElectron][icut].fPdgCode->Fill(mcpart->GetPdgCode());
550 fHist[iq][kElectron][icut].fPt->Fill(mcpart->Pt());
551 fHist[iq][kElectron][icut].fY->Fill(GetRapidity(mcpart));
552 fHist[iq][kElectron][icut].fEta->Fill(mcpart->Eta());
554 // fill mother hadron kinematics
555 fHist[iq][keHadron][icut].fPdgCode->Fill(maPdgcodeCopy);
556 fHist[iq][keHadron][icut].fPt->Fill(partMotherCopy->Pt());
557 fHist[iq][keHadron][icut].fY->Fill(GetRapidity(partMotherCopy));
558 fHist[iq][keHadron][icut].fEta->Fill(partMotherCopy->Eta());
560 // ratio between pT of electron and pT of mother B hadron
561 if(partMotherCopy->Pt()) fHistComm[iq][icut].fePtRatio->Fill(partMotherCopy->Pt(),mcpart->Pt()/partMotherCopy->Pt());
563 // distance between electron production point and mother hadron production point
564 TLorentzVector ebPoint;
565 partMotherCopy->ProductionVertex(ebPoint);
566 TLorentzVector edistance = ePoint - ebPoint;
567 fHistComm[iq][icut].feDistance->Fill(partMotherCopy->Pt(),edistance.P());
574 //__________________________________________
575 void AliHFEmcQA::IdentifyMother(Int_t motherlabel, Int_t &motherpdg, Int_t &grandmotherlabel)
577 // find mother pdg code and label
579 if (motherlabel < 0) {
580 AliDebug(1, "Stack label is negative, return\n");
583 TParticle *heavysMother = fStack->Particle(motherlabel);
584 motherpdg = heavysMother->GetPdgCode();
585 grandmotherlabel = heavysMother->GetFirstMother();
586 AliDebug(1,Form("ancestor pdg code= %d\n",motherpdg));
589 //__________________________________________
590 void AliHFEmcQA::HardScattering(const Int_t kquark, Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
592 // mothertype -1 means this heavy quark coming from hard vertex
594 TParticle *afterinitialrad1 = fStack->Particle(4);
595 TParticle *afterinitialrad2 = fStack->Particle(5);
599 if (abs(afterinitialrad1->GetPdgCode()) == fgkGluon && abs(afterinitialrad2->GetPdgCode()) == fgkGluon){
600 AliDebug(1,"heavy from gluon gluon pair creation!\n");
604 else if (abs(afterinitialrad1->GetPdgCode()) == kquark || abs(afterinitialrad2->GetPdgCode()) == kquark){ // one from Q and the other from g
605 AliDebug(1,"heavy from flavor exitation!\n");
609 else if (abs(afterinitialrad1->GetPdgCode()) == abs(afterinitialrad2->GetPdgCode())){
610 AliDebug(1,"heavy from q-qbar pair creation!\n");
615 AliDebug(1,"something strange!\n");
622 //__________________________________________
623 Bool_t AliHFEmcQA::IsFromInitialShower(Int_t inputmotherlabel, Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
625 // mothertype -2 means this heavy quark coming from initial state
627 if (inputmotherlabel==2 || inputmotherlabel==3){ // mother exist before initial state radiation
628 TParticle *heavysMother = fStack->Particle(inputmotherlabel);
629 motherID = heavysMother->GetPdgCode();
630 mothertype = -2; // there is mother before initial state radiation
631 motherlabel = inputmotherlabel;
632 AliDebug(1,"initial parton shower! \n");
640 //__________________________________________
641 Bool_t AliHFEmcQA::IsFromFinalParton(Int_t inputmotherlabel, Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
643 // mothertype 2 means this heavy quark coming from final state
645 if (inputmotherlabel > 5){ // mother exist after hard scattering
646 TParticle *heavysMother = fStack->Particle(inputmotherlabel);
647 motherID = heavysMother->GetPdgCode();
649 motherlabel = inputmotherlabel;
650 AliDebug(1,Form("heavy quark from %d after hard scattering! \n",motherID));
657 //__________________________________________
658 void AliHFEmcQA::ReportStrangeness(Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
660 // mark strange behavior
665 AliDebug(1,"something strange!\n");
668 //__________________________________________
669 Float_t AliHFEmcQA::GetRapidity(TParticle *part)
674 if(part->Energy() - part->Pz() == 0 || part->Energy() + part->Pz() == 0) rapidity=-999;
675 else rapidity = 0.5*(TMath::Log((part->Energy()+part->Pz()) / (part->Energy()-part->Pz())));