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 **************************************************************************/
16 // Secondary vertexing construction Class
17 // Construct secondary vertex from Beauty hadron with electron and
18 // hadrons, then apply selection criteria
21 // MinJung Kweon <minjung@physi.uni-heidelberg.de>
25 #include <TParticle.h>
27 #include <AliESDEvent.h>
28 #include <AliESDtrack.h>
29 #include "AliHFEsecVtx.h"
30 #include <AliKFParticle.h>
31 #include <AliKFVertex.h>
35 ClassImp(AliHFEsecVtx)
37 //_______________________________________________________________________________________________
38 AliHFEsecVtx::AliHFEsecVtx():
52 // Default constructor
58 //_______________________________________________________________________________________________
59 AliHFEsecVtx::AliHFEsecVtx(const AliHFEsecVtx &p):
63 ,fNparents(p.fNparents)
65 ,fPairTagged(p.fPairTagged)
66 ,fdistTwoSecVtx(p.fdistTwoSecVtx)
68 ,fsignedLxy(p.fsignedLxy)
70 ,finvmassSigma(p.finvmassSigma)
77 //_______________________________________________________________________________________________
79 AliHFEsecVtx::operator=(const AliHFEsecVtx &)
81 // Assignment operator
83 AliInfo("Not yet implemented.");
87 //_______________________________________________________________________________________________
88 AliHFEsecVtx::~AliHFEsecVtx()
92 //cout << "Analysis Done." << endl;
95 //__________________________________________
96 void AliHFEsecVtx::Init()
99 // set pdg code and index
103 fParentSelect[0][0] = 411;
104 fParentSelect[0][1] = 421;
105 fParentSelect[0][2] = 431;
106 fParentSelect[0][3] = 4122;
107 fParentSelect[0][4] = 4132;
108 fParentSelect[0][5] = 4232;
109 fParentSelect[0][6] = 4332;
111 fParentSelect[1][0] = 511;
112 fParentSelect[1][1] = 521;
113 fParentSelect[1][2] = 531;
114 fParentSelect[1][3] = 5122;
115 fParentSelect[1][4] = 5132;
116 fParentSelect[1][5] = 5232;
117 fParentSelect[1][6] = 5332;
167 //__________________________________________
168 void AliHFEsecVtx::ResetTagVar()
170 // reset tag variables
181 //__________________________________________
182 void AliHFEsecVtx::InitAnaPair()
184 // initialize pair tagging variables
187 for (Int_t i=0; i<20; i++){
188 fpairedTrackID[i] = -1;
190 fpairedInvMass[i] = -1;
191 fpairedSignedLxy[i] = -1;
240 //_______________________________________________________________________________________________
241 void AliHFEsecVtx::CreateHistograms(TString hnopt)
245 fkSourceLabel[kAll]="all";
246 fkSourceLabel[kDirectCharm]="directCharm";
247 fkSourceLabel[kDirectBeauty]="directBeauty";
248 fkSourceLabel[kBeautyCharm]="beauty2charm";
249 fkSourceLabel[kGamma]="gamma";
250 fkSourceLabel[kPi0]="pi0";
251 fkSourceLabel[kElse]="others";
252 fkSourceLabel[kBeautyGamma]="beauty22gamma";
253 fkSourceLabel[kBeautyPi0]="beauty22pi0";
254 fkSourceLabel[kBeautyElse]="beauty22others";
258 for (Int_t isource = 0; isource < 10; isource++ ){
260 hname=hnopt+"InvMass_"+fkSourceLabel[isource];
261 fHistPair[isource].fInvMass = new TH2F(hname,hname+";invMass;invMassSigma",120,-2,10,100,0,10);
262 hname=hnopt+"InvMassCut1_"+fkSourceLabel[isource];
263 fHistPair[isource].fInvMassCut1 = new TH2F(hname,hname+";invMass;invMassSigma",120,-2,10,100,0,10);
264 hname=hnopt+"InvMassCut2_"+fkSourceLabel[isource];
265 fHistPair[isource].fInvMassCut2 = new TH2F(hname,hname+";invMass;invMassSigma",120,-2,10,100,0,10);
266 hname=hnopt+"KFChi2_"+fkSourceLabel[isource];
267 fHistPair[isource].fKFChi2 = new TH1F(hname,hname,200,0,20);
268 hname=hnopt+"OpenAngle_"+fkSourceLabel[isource];
269 fHistPair[isource].fOpenAngle = new TH1F(hname,hname,100,0,3.14);
270 hname=hnopt+"CosOpenAngle_"+fkSourceLabel[isource];
271 fHistPair[isource].fCosOpenAngle = new TH1F(hname,hname,100,-1.1,1.1);
272 hname=hnopt+"SignedLxy_"+fkSourceLabel[isource];
273 fHistPair[isource].fSignedLxy = new TH2F(hname,hname,1000,-5,5,120,-2,10);
274 hname=hnopt+"KFIP_"+fkSourceLabel[isource];
275 fHistPair[isource].fKFIP = new TH1F(hname,hname,1000,-5,5);
276 hname=hnopt+"IPMax_"+fkSourceLabel[isource];
277 fHistPair[isource].fIPMax= new TH1F(hname,hname,500,0,5);
281 hname=hnopt+"pt_beautyelec";
282 fHistTagged.fPtBeautyElec= new TH1F(hname,hname,250,0,50);
283 hname=hnopt+"pt_taggedelec";
284 fHistTagged.fPtTaggedElec= new TH1F(hname,hname,250,0,50);
285 hname=hnopt+"pt_righttaggedelec";
286 fHistTagged.fPtRightTaggedElec = new TH1F(hname,hname,250,0,50);
287 hname=hnopt+"pt_wrongtaggedelec";
288 fHistTagged.fPtWrongTaggedElec = new TH1F(hname,hname,250,0,50);
290 hname=hnopt+"InvmassBeautyElecSecVtx";
291 fHistTagged.fInvmassBeautyElecSecVtx= new TH1F(hname,hname,120,-2,10);
292 hname=hnopt+"InvmassNotBeautyElecSecVtx";
293 fHistTagged.fInvmassNotBeautyElecSecVtx= new TH1F(hname,hname,120,-2,10);
295 hname=hnopt+"SignedLxyBeautyElecSecVtx";
296 fHistTagged.fSignedLxyBeautyElecSecVtx= new TH1F(hname,hname,1000,-5,5);
297 hname=hnopt+"SignedLxyNotBeautyElecSecVtx";
298 fHistTagged.fSignedLxyNotBeautyElecSecVtx= new TH1F(hname,hname,1000,-5,5);
300 hname=hnopt+"DistTwoVtxBeautyElecSecVtx";
301 fHistTagged.fDistTwoVtxBeautyElecSecVtx= new TH1F(hname,hname,1000,-5,5);
302 hname=hnopt+"DistTwoVtxNotBeautyElecSecVtx";
303 fHistTagged.fDistTwoVtxNotBeautyElecSecVtx= new TH1F(hname,hname,1000,-5,5);
305 hname=hnopt+"CosPhiBeautyElecSecVtx";
306 fHistTagged.fCosPhiBeautyElecSecVtx= new TH1F(hname,hname,100,-1.1,1.1);
307 hname=hnopt+"CosPhiNotBeautyElecSecVtx";
308 fHistTagged.fCosPhiNotBeautyElecSecVtx= new TH1F(hname,hname,100,-1.1,1.1);
310 hname=hnopt+"Chi2BeautyElecSecVtx";
311 fHistTagged.fChi2BeautyElecSecVtx= new TH1F(hname,hname,200,0,20);
312 hname=hnopt+"Chi2NotBeautyElecSecVtx";
313 fHistTagged.fChi2NotBeautyElecSecVtx= new TH1F(hname,hname,200,0,20);
315 hname=hnopt+"InvmassBeautyElec2trkVtx";
316 fHistTagged.fInvmassBeautyElec2trkVtx= new TH1F(hname,hname,120,-2,10);
317 hname=hnopt+"InvmassNotBeautyElec2trkVtx";
318 fHistTagged.fInvmassNotBeautyElec2trkVtx= new TH1F(hname,hname,120,-2,10);
320 hname=hnopt+"SignedLxyBeautyElec2trkVtx";
321 fHistTagged.fSignedLxyBeautyElec2trkVtx= new TH1F(hname,hname,1000,-5,5);
322 hname=hnopt+"SignedLxyNotBeautyElec2trkVtx";
323 fHistTagged.fSignedLxyNotBeautyElec2trkVtx= new TH1F(hname,hname,1000,-5,5);
325 hname=hnopt+"Chi2BeautyElec2trkVtx";
326 fHistTagged.fChi2BeautyElec2trkVtx= new TH1F(hname,hname,200,0,20);
327 hname=hnopt+"Chi2NotBeautyElec2trkVtx";
328 fHistTagged.fChi2NotBeautyElec2trkVtx= new TH1F(hname,hname,200,0,20);
331 //_______________________________________________________________________________________________
332 void AliHFEsecVtx::AnaPair(AliESDtrack* track1, AliESDtrack* track2, Int_t index2)
334 // calculate e-h pair characteristics and tag pair
336 Int_t sourcePart = PairCode(track1,track2);
338 // get KF particle input pid
339 Int_t pdg1 = GetMCPID(track1);
340 Int_t pdg2 = GetMCPID(track2);
343 // create KF particle of pair
344 AliKFParticle::SetField(fESD1->GetMagneticField());
345 AliKFParticle kfTrack1(*track1, pdg1);
346 AliKFParticle kfTrack2(*track2, pdg2);
348 AliKFParticle kfSecondary(kfTrack1,kfTrack2);
350 // copy primary vertex from ESD
351 AliKFVertex primVtxCopy(*(fESD1->GetPrimaryVertex()));
352 if( primVtxCopy.GetNDF() <1 ) return;
354 //primary vertex point
355 Double_t pvx = primVtxCopy.GetX();
356 Double_t pvy = primVtxCopy.GetY();
357 //Double_t pvz = primVtxCopy.GetZ();
359 //secondary vertex point from kf particle
360 Double_t kfx = kfSecondary.GetX();
361 Double_t kfy = kfSecondary.GetY();
362 //Double_t kfz = kfSecondary.GetZ();
364 //momentum at the decay point from kf particle
365 Double_t kfpx = kfSecondary.GetPx();
366 Double_t kfpy = kfSecondary.GetPy();
367 //Double_t kfpz = kfSecondary.GetPz();
370 Double_t dx = kfx-pvx;
371 Double_t dy = kfy-pvy;
375 // discriminating variables ----------------------------------------------------------
377 // invariant mass of the KF particle
378 Double_t invmass = -1;
379 Double_t invmassSigma = -1;
380 kfSecondary.GetMass(invmass,invmassSigma);
382 // chi2 of the KF particle
383 Double_t kfchi2 = TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
385 // opening angle between two particles in XY plane
386 Double_t phi = kfTrack1.GetAngleXY(kfTrack2);
387 Double_t cosphi = TMath::Cos(phi);
389 // projection of kf vertex vector to the kf momentum direction
390 Double_t costheta = ( dx*kfpx + dy*kfpy)/TMath::Sqrt(dx*dx+dy*dy)*TMath::Sqrt(kfpx*kfpx + kfpy*kfpy);
391 Double_t signedLxy = TMath::Sqrt(dx*dx+dy*dy)*costheta;
393 // DCA from primary to e-h KF particle (impact parameter of KF particle)
394 Double_t vtx[2]={pvx, pvy};
395 Double_t kfip = kfSecondary.GetDistanceFromVertexXY(vtx);
399 Float_t dcaR1=-1, dcaR2=-1;
400 Float_t dcaZ1=-1, dcaZ2=-1;
401 track1->GetImpactParameters(dcaR1,dcaZ1);
402 track2->GetImpactParameters(dcaR2,dcaZ2);
404 if (TMath::Abs(dcaR1) >= TMath::Abs(dcaR2)) dcaR=dcaR1;
408 fHistPair[sourcePart].fInvMass->Fill(invmass,invmassSigma);
409 fHistPair[sourcePart].fKFChi2->Fill(kfchi2);
410 fHistPair[sourcePart].fOpenAngle->Fill(phi);
411 fHistPair[sourcePart].fCosOpenAngle->Fill(cosphi);
412 fHistPair[sourcePart].fSignedLxy->Fill(signedLxy,invmass);
413 fHistPair[sourcePart].fKFIP->Fill(kfip);
414 fHistPair[sourcePart].fIPMax->Fill(TMath::Abs(dcaR));
417 if( kfchi2 >2. ) return;
419 if ( signedLxy > 0.05 && cosphi > 0.5) fHistPair[sourcePart].fInvMassCut1->Fill(invmass,invmassSigma);
421 // pair tagging if it passed the above cuts
422 if(signedLxy > 0. && cosphi > 0.) fHistPair[sourcePart].fInvMassCut2->Fill(invmass,invmassSigma);
425 // pair tagging condition
426 if ( signedLxy > 0.0 && cosphi > 0) { // testing loose cut
427 //if ( signedLxy > 0.06 && cosphi > 0) {
428 fpairedTrackID[fPairTagged] = index2;
429 fpairedChi2[fPairTagged] = kfchi2;
430 fpairedInvMass[fPairTagged] = invmass;
431 fpairedSignedLxy[fPairTagged] = signedLxy;
437 //_______________________________________________________________________________________________
438 void AliHFEsecVtx::RunSECVTX(AliESDtrack *track)
440 // run secondary vertexing algorithm and do tagging
444 Int_t imclabel = TMath::Abs(track->GetLabel());
445 if(imclabel<0) return;
446 TParticle* mcpart = fStack->Particle(imclabel);
447 Int_t esource = GetElectronSource(imclabel);
448 if (esource == kDirectBeauty || esource == kBeautyCharm || esource == kBeautyGamma || esource == kBeautyPi0 || esource == kBeautyElse){
449 fHistTagged.fPtBeautyElec->Fill(mcpart->Pt());
454 if (fPairTagged >= 4) {
455 FindSECVTXCandid4Tracks(track);
457 else if (fPairTagged == 3) {
458 FindSECVTXCandid3Tracks(track);
460 else if (fPairTagged == 2) {
461 FindSECVTXCandid2Tracks(track);
463 else if (fPairTagged == 1) {
469 fHistTagged.fPtTaggedElec->Fill(mcpart->Pt());
470 if (esource == kDirectBeauty || esource == kBeautyCharm || esource == kBeautyGamma || esource == kBeautyPi0 || esource == kBeautyElse){
471 fHistTagged.fPtRightTaggedElec->Fill(mcpart->Pt());
473 else fHistTagged.fPtWrongTaggedElec->Fill(mcpart->Pt());
478 //_______________________________________________________________________________________________
479 void AliHFEsecVtx::ApplyPairTagCut()
481 // apply tagging cut for e-h pair
484 fHistTagged.fInvmassBeautyElec2trkVtx->Fill(fpairedInvMass[0]);
485 fHistTagged.fSignedLxyBeautyElec2trkVtx->Fill(fpairedSignedLxy[0]);
486 fHistTagged.fChi2BeautyElec2trkVtx->Fill(fpairedChi2[0]);
489 fHistTagged.fInvmassNotBeautyElec2trkVtx->Fill(fpairedInvMass[0]);
490 fHistTagged.fSignedLxyNotBeautyElec2trkVtx->Fill(fpairedSignedLxy[0]);
491 fHistTagged.fChi2NotBeautyElec2trkVtx->Fill(fpairedChi2[0]);
494 if (fpairedChi2[0] > 2.0) return;
495 if (fpairedInvMass[0] < 1.5) return;
496 if (fpairedSignedLxy[0] < 0.05) return;
501 //_______________________________________________________________________________________________
502 Bool_t AliHFEsecVtx::ApplyPairTagCut(Int_t id)
504 // apply tagging cut for e-h pair of given indexed hadron
506 if (fpairedChi2[id] > 2.0) return kFALSE;
507 if (fpairedInvMass[id] < 1.5) return kFALSE;
508 if (fpairedSignedLxy[id] < 0.05) return kFALSE;
515 //_______________________________________________________________________________________________
516 Bool_t AliHFEsecVtx::ApplyTagCut(Double_t chi2)
518 // apply tagging cut for secondary vertex
520 if (chi2 > 2.0) return kFALSE;
521 if (finvmass < 1.5) return kFALSE;
522 if (fsignedLxy < 0.05) return kFALSE;
523 if (fcosPhi < 0.90) return kFALSE;
524 if (fdistTwoSecVtx > 0.1) return kFALSE;
530 //_______________________________________________________________________________________________
531 void AliHFEsecVtx::ApplyVtxTagCut(Double_t chi2, Int_t id1, Int_t id2)
533 // apply tagging cut for e-h pair of given indexed hadron
535 if(!ApplyTagCut(chi2)){
536 if(!ApplyPairTagCut(id1)) ApplyPairTagCut(id2);
541 //_______________________________________________________________________________________________
542 void AliHFEsecVtx::FindSECVTXCandid4Tracks(AliESDtrack *track)
544 // find secondary vertex for >= 4 e-h pairs
546 // sort pair in increasing order (kFALSE-increasing order)
551 AliESDtrack *htrack[4];
553 if(fPairTagged>20) return; // protection
555 TMath::Sort(fPairTagged,fpairedChi2,index,kFALSE);
557 // select 4 partner tracks retruning smallest pair chi2
559 for (Int_t i=0; i<4; i++){
560 htrack[i] = fESD1->GetTrack(fpairedTrackID[index[i]]);
563 // calculated chi2 with 1 electron and 3 partner tracks
564 for (Int_t i=0; i<4; i++){
565 sevchi2[i] = GetSecVtxChi2(track, htrack[fid[i][0]], htrack[fid[i][1]], htrack[fid[i][2]]);
568 // select 3 partner tracks retruning smallest pair chi2
569 // [think] if two smallest chi2 are similar, have to think about better handling of selection
570 TMath::Sort(4,sevchi2,indexA,kFALSE);
572 // calculated chi2 with 1 electron and 2 partner tracks
573 for (Int_t i=0; i<3; i++){
574 sevchi2[i] = GetSecVtxChi2(track, htrack[fia[indexA[0]][i][0]], htrack[fia[indexA[0]][i][1]]);
577 // select 2 partner tracks retruning smallest pair chi2
578 TMath::Sort(3,sevchi2,indexB,kFALSE);
580 // calculate secondary vertex quality variables with 1 electron and 2 hadrons
581 CalcSECVTXProperty(track,htrack[fia[indexA[0]][indexB[0]][0]],htrack[fia[indexA[0]][indexB[0]][1]]);
584 fHistTagged.fChi2BeautyElecSecVtx->Fill(sevchi2[indexB[0]]);
587 fHistTagged.fChi2NotBeautyElecSecVtx->Fill(sevchi2[indexB[0]]);
590 ApplyVtxTagCut(sevchi2[indexB[0]],index[fia[indexA[0]][indexB[0]][0]],index[fia[indexA[0]][indexB[0]][1]]);
594 //_______________________________________________________________________________________________
595 void AliHFEsecVtx::FindSECVTXCandid3Tracks(AliESDtrack *track)
597 // find secondary vertex for 3 e-h pairs
599 // sort pair in increasing order (kFALSE-increasing order)
600 Int_t indexA[1] = { 0 };
603 AliESDtrack *htrack[3];
605 // select 4 partner tracks retruning smallest pair chi2
607 for (Int_t i=0; i<3; i++){
608 htrack[i] = fESD1->GetTrack(fpairedTrackID[i]);
611 // calculated chi2 with 1 electron and 2 partner tracks
612 for (Int_t i=0; i<3; i++){
613 sevchi2[i] = GetSecVtxChi2(track, htrack[fia[indexA[0]][i][0]], htrack[fia[indexA[0]][i][1]]);
616 // select 2 partner tracks retruning smallest pair chi2
617 TMath::Sort(3,sevchi2,indexB,kFALSE);
619 // calculate secondary vertex quality variables with 1 electron and 2 hadrons
620 CalcSECVTXProperty(track,htrack[fia[indexA[0]][indexB[0]][0]],htrack[fia[indexA[0]][indexB[0]][1]]);
623 fHistTagged.fChi2BeautyElecSecVtx->Fill(sevchi2[indexB[0]]);
626 fHistTagged.fChi2NotBeautyElecSecVtx->Fill(sevchi2[indexB[0]]);
629 ApplyVtxTagCut(sevchi2[indexB[0]],fia[indexA[0]][indexB[0]][0],fia[indexA[0]][indexB[0]][1]);
632 //_______________________________________________________________________________________________
633 void AliHFEsecVtx::FindSECVTXCandid2Tracks(AliESDtrack *track)
635 // find secondary vertex for 2 e-h pairs
638 AliESDtrack *htrack[2];
640 for (Int_t i=0; i<2; i++){
641 htrack[i] = fESD1->GetTrack(fpairedTrackID[i]);
644 sevchi2[0] = GetSecVtxChi2(track, htrack[0], htrack[1]);
646 // calculate secondary vertex quality variables with 1 electron and 2 hadrons
647 CalcSECVTXProperty(track,htrack[0],htrack[1]);
650 fHistTagged.fChi2BeautyElecSecVtx->Fill(sevchi2[0]);
653 fHistTagged.fChi2NotBeautyElecSecVtx->Fill(sevchi2[0]);
656 ApplyVtxTagCut(sevchi2[0],0,1);
659 //_______________________________________________________________________________________________
660 void AliHFEsecVtx::CalcSECVTXProperty(AliESDtrack* track1, AliESDtrack* track2, AliESDtrack* track3)
662 // calculate secondary vertex properties
664 Int_t pdg1 = GetMCPID(track1);
665 Int_t pdg2 = GetMCPID(track2);
666 Int_t pdg3 = GetMCPID(track3);
668 AliKFParticle::SetField(fESD1->GetMagneticField());
669 AliKFParticle kfTrack1(*track1, pdg1);
670 AliKFParticle kfTrack2(*track2, pdg2);
671 AliKFParticle kfTrack3(*track3, pdg3);
673 AliKFParticle kfSecondary12(kfTrack1,kfTrack2);
674 AliKFParticle kfSecondary13(kfTrack1,kfTrack3);
675 AliKFParticle kfSecondary(kfTrack1,kfTrack2,kfTrack3);
677 // copy primary vertex from ESD
678 AliKFVertex primVtxCopy(*(fESD1->GetPrimaryVertex()));
679 //printf("primary ndf= %d\n",primVtxCopy.GetNDF());
680 if( primVtxCopy.GetNDF() <1 ) return;
682 Double_t kdx12 = kfSecondary12.GetX()-primVtxCopy.GetX();
683 Double_t kdy12 = kfSecondary12.GetY()-primVtxCopy.GetY();
684 //Double_t kdz12 = kfSecondary12.GetZ()-primVtxCopy.GetZ();
686 Double_t kdx13 = kfSecondary13.GetX()-primVtxCopy.GetX();
687 Double_t kdy13 = kfSecondary13.GetY()-primVtxCopy.GetY();
688 //Double_t kdz13 = kfSecondary13.GetZ()-primVtxCopy.GetZ();
690 Double_t kdx = kfSecondary.GetX()-primVtxCopy.GetX();
691 Double_t kdy = kfSecondary.GetY()-primVtxCopy.GetY();
692 //Double_t kdz = kfSecondary.GetZ()-primVtxCopy.GetZ();
694 // calculate distance and angle between two secvtxes
695 fdistTwoSecVtx = TMath::Sqrt((kdx12-kdx13)*(kdx12-kdx13) + (kdy12-kdy13)*(kdy12-kdy13));
696 fcosPhi = ( kdx12*kdx13 + kdy12*kdy13 ) / ( TMath::Sqrt(kdx12*kdx12+kdy12*kdy12)*TMath::Sqrt(kdx13*kdx13+kdy13*kdy13) );
697 //Double_t lengthdiff = TMath::Abs(TMath::Sqrt(kdx12*kdx12+kdy12*kdy12) - TMath::Sqrt(kdx13*kdx13+kdy13*kdy13));
699 // calculate angle between secondary vertex vector and secondary particle momentum vector in transverse plane
700 Double_t cosTheta = ( kdx*kfSecondary.GetPx() + kdy*kfSecondary.GetPy()) / TMath::Sqrt(kdx*kdx+kdy*kdy)*TMath::Sqrt(kfSecondary.GetPx()*kfSecondary.GetPx()+kfSecondary.GetPy()*kfSecondary.GetPy());
701 // calculate signed Lxy
702 fsignedLxy = TMath::Sqrt(kdx*kdx+kdy*kdy)*cosTheta;
704 // calculate invariant mass of the kf particle
705 kfSecondary.GetMass(finvmass,finvmassSigma);
708 fHistTagged.fInvmassBeautyElecSecVtx->Fill(finvmass);
709 fHistTagged.fSignedLxyBeautyElecSecVtx->Fill(fsignedLxy);
710 fHistTagged.fDistTwoVtxBeautyElecSecVtx->Fill(fdistTwoSecVtx);
711 fHistTagged.fCosPhiBeautyElecSecVtx->Fill(fcosPhi);
714 fHistTagged.fInvmassNotBeautyElecSecVtx->Fill(finvmass);
715 fHistTagged.fSignedLxyNotBeautyElecSecVtx->Fill(fsignedLxy);
716 fHistTagged.fDistTwoVtxNotBeautyElecSecVtx->Fill(fdistTwoSecVtx);
717 fHistTagged.fCosPhiNotBeautyElecSecVtx->Fill(fcosPhi);
722 //_______________________________________________________________________________________________
723 Int_t AliHFEsecVtx::GetMCPID(AliESDtrack *track)
727 Int_t label = TMath::Abs(track->GetLabel());
728 TParticle* mcpart = fStack->Particle(label);
729 if ( !mcpart ) return 0;
730 Int_t pdgCode = mcpart->GetPdgCode();
735 //_______________________________________________________________________________________________
736 Double_t AliHFEsecVtx::GetSecVtxChi2(AliESDtrack* track1, AliESDtrack* track2, AliESDtrack* track3, AliESDtrack* track4)
738 // return 4 track secondary vertex chi2
740 Int_t pdg1 = GetMCPID(track1);
741 Int_t pdg2 = GetMCPID(track2);
742 Int_t pdg3 = GetMCPID(track3);
743 Int_t pdg4 = GetMCPID(track4);
745 AliKFParticle::SetField(fESD1->GetMagneticField());
746 AliKFParticle kfTrack1(*track1, pdg1);
747 AliKFParticle kfTrack2(*track2, pdg2);
748 AliKFParticle kfTrack3(*track3, pdg3);
749 AliKFParticle kfTrack4(*track4, pdg4);
750 AliKFParticle kfSecondary(kfTrack1,kfTrack2,kfTrack3,kfTrack4);
752 return TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
756 //_______________________________________________________________________________________________
757 Double_t AliHFEsecVtx::GetSecVtxChi2(AliESDtrack* track1, AliESDtrack* track2, AliESDtrack* track3)
759 // return 3 track secondary vertex chi2
761 Int_t pdg1 = GetMCPID(track1);
762 Int_t pdg2 = GetMCPID(track2);
763 Int_t pdg3 = GetMCPID(track3);
765 AliKFParticle::SetField(fESD1->GetMagneticField());
766 AliKFParticle kfTrack1(*track1, pdg1);
767 AliKFParticle kfTrack2(*track2, pdg2);
768 AliKFParticle kfTrack3(*track3, pdg3);
769 AliKFParticle kfSecondary(kfTrack1,kfTrack2,kfTrack3);
771 return TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
775 //_______________________________________________________________________________________________
776 Double_t AliHFEsecVtx::GetSecVtxChi2(AliESDtrack* track1, AliESDtrack* track2)
778 // return 2 track secondary vertex chi2
780 Int_t pdg1 = GetMCPID(track1);
781 Int_t pdg2 = GetMCPID(track2);
783 AliKFParticle::SetField(fESD1->GetMagneticField());
784 AliKFParticle kfTrack1(*track1, pdg1);
785 AliKFParticle kfTrack2(*track2, pdg2);
786 AliKFParticle kfSecondary(kfTrack1,kfTrack2);
788 return TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
792 //_______________________________________________________________________________________________
793 Int_t AliHFEsecVtx::PairOrigin(AliESDtrack* track1, AliESDtrack* track2)
797 // return pdg code of the origin(source) of the pair
800 // ---*---*---*-----ancester A----- track1
803 // => if they originated from same ancester,
804 // then return "the absolute value of pdg code of ancester A"
806 // ---*---*---B hadron-----ancester A----- track1
809 // => if they originated from same ancester, and this ancester originally comes from B hadrons
810 // then return -1*"the absolute value of pdg code of ancester A"
812 // caution : it can also return parton pdg code if it originated from same string or gluon spliting.
815 if (track1->GetLabel()<0 || track2->GetLabel()<0) return 0;
816 TParticle* part1 = fStack->Particle(TMath::Abs(track1->GetLabel()));
817 TParticle* part2 = fStack->Particle(TMath::Abs(track2->GetLabel()));
818 if (!(part1)) return 0;
819 if (!(part2)) return 0;
821 TParticle* part1Crtgen = part1; // copy track into current generation particle
822 TParticle* part2Crtgen = part2; // copy track into current generation particle
827 // if the two tracks' mother's label is same, get the mother info
828 // in case of charm, check if it originated from beauty
829 for (Int_t i=0; i<100; i++){ // iterate 100
830 Int_t iLabel = part1Crtgen->GetFirstMother(); //label of mother of current generation for 1st partilce
831 if (iLabel < 0) return 0;
833 for (Int_t j=0; j<100; j++){ // iterate 100
834 Int_t jLabel = part2Crtgen->GetFirstMother(); //label of mother of current generation for 2nd partilce
835 if (jLabel < 0) return 0; // if jLabel == -1
837 if (iLabel == jLabel){ // check if two tracks are originated from same mother
838 TParticle* thismother = fStack->Particle(jLabel); // if yes, get "thismother" info
839 sourcePDG = abs(thismother->GetPdgCode()); // get the pdg code of "this mother"
841 // check ancester to see if it is originally from beauty
842 for (Int_t k=0; k<10; k++){ // check up to 10 ancesters
843 Int_t ancesterLabel = thismother->GetFirstMother();
844 if (ancesterLabel < 0) return sourcePDG; // if "thismoter" doesn't have mother anymore, return thismother's pdg
846 TParticle* thisancester = fStack->Particle(ancesterLabel);
847 Int_t ancesterPDG = abs(thisancester->GetPdgCode());
849 for (Int_t l=0; l<fNparents; l++){
850 if (abs(ancesterPDG)==fParentSelect[1][l]){
851 sourcePDG = -1*sourcePDG; // multiply -1 for charm from bottom
855 thismother = thisancester;
859 part2Crtgen = fStack->Particle(jLabel); // if their mother is different, go up to previous generation of 2nd particle
861 part1Crtgen = fStack->Particle(iLabel); // if their mother is different, go up to previous generation of 2nd particle
863 // if you don't find additionional(2nd particle) track originated from a given beauty hadron, break to save time
864 Int_t motherPDGtmp = abs(part1Crtgen->GetPdgCode());
865 for (Int_t l=0; l<fNparents; l++){
866 if (abs(motherPDGtmp)==fParentSelect[1][l]) return sourcePDG;
875 //_______________________________________________________________________________________________
876 Int_t AliHFEsecVtx::PairCode(AliESDtrack* track1,AliESDtrack* track2)
880 // return pair code which is predefinded as:
881 // kDirectCharm, kDirectBeauty, kBeautyCharm, kGamma, kPi0, kElse, kBeautyGamma, kBeautyPi0, kBeautyElse
884 Int_t pairOriginsPDG = PairOrigin(track1,track2);
886 Int_t sourcePart = kElse;
888 if (pairOriginsPDG < 0) {
889 sourcePart = kBeautyElse;
891 for (Int_t i=0; i<fNparents; i++){
892 if (abs(pairOriginsPDG)==fParentSelect[0][i]) {
893 if (pairOriginsPDG>0) sourcePart = kDirectCharm;
894 if (pairOriginsPDG<0) {
895 sourcePart = kBeautyCharm;
898 if (abs(pairOriginsPDG)==fParentSelect[1][i]) {
899 if (pairOriginsPDG>0) {
900 sourcePart = kDirectBeauty;
902 if (pairOriginsPDG<0) return kElse;
905 if (pairOriginsPDG == 22) sourcePart = kGamma;
906 if (pairOriginsPDG == -22) {
907 sourcePart = kBeautyGamma;
909 if (pairOriginsPDG == 111) sourcePart = kPi0;
910 if (pairOriginsPDG == -111) {
911 sourcePart = kBeautyPi0;
918 //_______________________________________________________________________________________________
919 Int_t AliHFEsecVtx::GetElectronSource(Int_t iTrack)
922 // return decay electron's origin
925 AliDebug(1, "Stack label is negative, return\n");
929 TParticle* mcpart = fStack->Particle(iTrack);
931 if ( abs(mcpart->GetPdgCode()) != 11 ) return -1; // check if it is electron !!!!!!!!!!!!!!!!!
933 Int_t iLabel = mcpart->GetFirstMother();
935 AliDebug(1, "Stack label is negative, return\n");
940 Bool_t isFinalOpenCharm = kFALSE;
942 TParticle *partMother = fStack->Particle(iLabel);
943 Int_t maPdgcode = partMother->GetPdgCode();
945 // if the mother is charmed hadron
946 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
948 for (Int_t i=0; i<fNparents; i++){
949 if (abs(maPdgcode)==fParentSelect[0][i]){
950 isFinalOpenCharm = kTRUE;
953 if (!isFinalOpenCharm) return -1;
956 // iterate until you find B hadron as a mother or become top ancester
957 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
959 Int_t jLabel = partMother->GetFirstMother();
961 origin = kDirectCharm;
964 if (jLabel < 0){ // safety protection
965 AliDebug(1, "Stack label is negative, return\n");
969 // if there is an ancester
970 TParticle* grandMa = fStack->Particle(jLabel);
971 Int_t grandMaPDG = grandMa->GetPdgCode();
973 for (Int_t j=0; j<fNparents; j++){
974 if (abs(grandMaPDG)==fParentSelect[1][j]){
976 origin = kBeautyCharm;
981 partMother = grandMa;
982 } // end of iteration
984 else if ( int(abs(maPdgcode)/100.) == kBeauty || int(abs(maPdgcode)/1000.) == kBeauty ) {
985 for (Int_t i=0; i<fNparents; i++){
986 if (abs(maPdgcode)==fParentSelect[1][i]){
987 origin = kDirectBeauty;
994 //============ gamma ================
995 else if ( abs(maPdgcode) == 22 ) {
998 // iterate until you find B hadron as a mother or become top ancester
999 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1001 Int_t jLabel = partMother->GetFirstMother();
1006 if (jLabel < 0){ // safety protection
1007 AliDebug(1, "Stack label is negative, return\n");
1011 // if there is an ancester
1012 TParticle* grandMa = fStack->Particle(jLabel);
1013 Int_t grandMaPDG = grandMa->GetPdgCode();
1015 for (Int_t j=0; j<fNparents; j++){
1016 if (abs(grandMaPDG)==fParentSelect[1][j]){
1017 origin = kBeautyGamma;
1022 partMother = grandMa;
1023 } // end of iteration
1028 //============ pi0 ================
1029 else if ( abs(maPdgcode) == 111 ) {
1032 // iterate until you find B hadron as a mother or become top ancester
1033 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1035 Int_t jLabel = partMother->GetFirstMother();
1040 if (jLabel < 0){ // safety protection
1041 AliDebug(1, "Stack label is negative, return\n");
1045 // if there is an ancester
1046 TParticle* grandMa = fStack->Particle(jLabel);
1047 Int_t grandMaPDG = grandMa->GetPdgCode();
1049 for (Int_t j=0; j<fNparents; j++){
1050 if (abs(grandMaPDG)==fParentSelect[1][j]){
1051 origin = kBeautyPi0;
1056 partMother = grandMa;
1057 } // end of iteration
1066 // iterate until you find B hadron as a mother or become top ancester
1067 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1069 Int_t jLabel = partMother->GetFirstMother();
1074 if (jLabel < 0){ // safety protection
1075 AliDebug(1, "Stack label is negative, return\n");
1079 // if there is an ancester
1080 TParticle* grandMa = fStack->Particle(jLabel);
1081 Int_t grandMaPDG = grandMa->GetPdgCode();
1083 for (Int_t j=0; j<fNparents; j++){
1084 if (abs(grandMaPDG)==fParentSelect[1][j]){
1085 origin = kBeautyElse;
1090 partMother = grandMa;
1091 } // end of iteration
1100 //_______________________________________________________________________________________________
1101 Int_t AliHFEsecVtx::GetElectronSource(Int_t iTrackLabel)
1105 // decay electron's origin
1108 if (iTrackLabel < 0) {
1109 AliDebug(1, "Stack label is negative, return\n");
1113 TParticle* mcpart = fStack->Particle(iTrackLabel);
1114 Int_t iLabel = mcpart->GetFirstMother();
1116 AliDebug(1, "Stack label is negative, return\n");
1121 Bool_t isFinalOpenCharm = kFALSE;
1123 TParticle *partMother = fStack->Particle(iLabel);
1124 Int_t maPdgcode = partMother->GetPdgCode(); // get mother's pdg code
1126 //beauty --------------------------
1127 if ( int(abs(maPdgcode)/100.) == kBeauty || int(abs(maPdgcode)/1000.) == kBeauty ) {
1128 for (Int_t i=0; i<fNparents; i++){
1129 if (abs(maPdgcode)==fParentSelect[1][i]){
1130 origin = kDirectBeauty;
1133 else return -1; // this track is originated beauties not in the final B hadron list => excited beauties
1137 //charm --------------------------
1138 else if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
1140 for (Int_t i=0; i<fNparents; i++){
1141 if (abs(maPdgcode)==fParentSelect[0][i])
1142 isFinalOpenCharm = kTRUE;
1144 if (!isFinalOpenCharm) return -1; // this track is originated charms not in the final D hadron list => excited charms
1145 // to prevent any possible double counting
1147 for (Int_t i=0; i<100; i++){ // iterate 100 until you find B hadron as a mother or become top ancester
1149 Int_t jLabel = partMother->GetFirstMother();
1151 origin = kDirectCharm;
1154 if (jLabel < 0){ // safety protection even though not really necessary here
1155 AliDebug(1, "Stack label is negative, return\n");
1159 // if there is an ancester, check if it in the final B hadron list
1160 TParticle* grandMa = fStack->Particle(jLabel);
1161 Int_t grandMaPDG = grandMa->GetPdgCode();
1163 for (Int_t j=0; j<fNparents; j++){
1164 if (abs(grandMaPDG)==fParentSelect[1][j]){
1165 origin = kBeautyCharm;
1170 partMother = grandMa;
1171 } // end of iteration
1174 //gamma --------------------------
1175 else if ( abs(maPdgcode) == 22 ) {
1178 // iterate until you find B hadron as a mother or become top ancester
1179 for (Int_t i=0; i<100; i++){ // check back to the 100 generation older
1181 Int_t jLabel = partMother->GetFirstMother();
1186 if (jLabel < 0){ // safety protection
1187 AliDebug(1, "Stack label is negative, return\n");
1191 // if there is an ancester
1192 TParticle* grandMa = fStack->Particle(jLabel);
1193 Int_t grandMaPDG = grandMa->GetPdgCode();
1195 for (Int_t j=0; j<fNparents; j++){
1196 if (abs(grandMaPDG)==fParentSelect[1][j]){
1197 origin = kBeautyGamma;
1202 partMother = grandMa;
1203 } // end of iteration
1208 //pi0 --------------------------
1209 else if ( abs(maPdgcode) == 111 ) {
1212 // iterate until you find B hadron as a mother or become top ancester
1213 for (Int_t i=0; i<100; i++){ // check back to the 100 generation older
1215 Int_t jLabel = partMother->GetFirstMother();
1220 if (jLabel < 0){ // safety protection
1221 AliDebug(1, "Stack label is negative, return\n");
1225 // if there is an ancester
1226 TParticle* grandMa = fStack->Particle(jLabel);
1227 Int_t grandMaPDG = grandMa->GetPdgCode();
1229 for (Int_t j=0; j<fNparents; j++){
1230 if (abs(grandMaPDG)==fParentSelect[1][j]){
1231 origin = kBeautyPi0;
1236 partMother = grandMa;
1237 } // end of iteration
1243 //else --------------------------
1247 // iterate until you find B hadron as a mother or become top ancester
1248 for (Int_t i=0; i<100; i++){ // check back to the 100 generation older
1250 Int_t jLabel = partMother->GetFirstMother();
1255 if (jLabel < 0){ // safety protection
1256 AliDebug(1, "Stack label is negative, return\n");
1260 // if there is an ancester
1261 TParticle* grandMa = fStack->Particle(jLabel);
1262 Int_t grandMaPDG = grandMa->GetPdgCode();
1264 for (Int_t j=0; j<fNparents; j++){
1265 if (abs(grandMaPDG)==fParentSelect[1][j]){
1266 origin = kBeautyElse;
1271 partMother = grandMa;
1272 } // end of iteration
1281 //_______________________________________________________________________________________________
1282 Bool_t AliHFEsecVtx::SingleTrackCut(AliESDtrack* track) const
1286 //if (track->Pt() < 1.0) return kFALSE;
1287 //if (TMath::Abs(track->Eta()) > 0.9) return kFALSE;
1288 //if (!(track->GetStatus() & AliESDtrack::kITSrefit)) return kFALSE;
1289 //if (!(track->GetStatus() & AliESDtrack::kTPCrefit)) return kFALSE;
1290 if (!(TESTBIT(track->GetITSClusterMap(),0))) return kFALSE; // ask hit on the first pixel layer
1291 //if (!(TESTBIT(track->GetITSClusterMap(),0) | TESTBIT(track->GetITSClusterMap(),1))) return kFALSE;
1297 track->GetImpactParameters(dcaR,dcaZ);
1298 if (TMath::Abs(TMath::Sqrt(dcaR*dcaR + dcaZ*dcaZ)) < 0.005) return kFALSE;
1299 if (TMath::Abs(TMath::Sqrt(dcaR*dcaR + dcaZ*dcaZ)) > 0.3) return kFALSE;