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 <TIterator.h>
26 #include <TParticle.h>
28 #include <AliESDVertex.h>
29 #include <AliESDEvent.h>
30 #include <AliAODEvent.h>
31 #include <AliVTrack.h>
32 #include <AliESDtrack.h>
33 #include <AliAODTrack.h>
34 #include "AliHFEsecVtx.h"
35 #include <AliKFParticle.h>
36 #include <AliKFVertex.h>
38 #include <AliMCEvent.h>
39 #include <AliAODMCParticle.h>
40 #include "AliHFEpairs.h"
41 #include "AliHFEsecVtxs.h"
42 #include "AliHFEtrackFilter.h"
43 #include "AliHFEmcQA.h"
44 #include "AliHFEtools.h"
46 ClassImp(AliHFEsecVtx)
48 //_______________________________________________________________________________________________
49 AliHFEsecVtx::AliHFEsecVtx():
87 // Default constructor
93 //_______________________________________________________________________________________________
94 AliHFEsecVtx::AliHFEsecVtx(const AliHFEsecVtx &p):
101 ,fUseMCPID(p.fUseMCPID)
103 ,fNparents(p.fNparents)
107 ,fNoOfHFEpairs(p.fNoOfHFEpairs)
108 ,fNoOfHFEsecvtxs(p.fNoOfHFEsecvtxs)
109 ,fArethereSecVtx(p.fArethereSecVtx)
118 ,fSignedLxy(p.fSignedLxy)
119 ,fSignedLxy2(p.fSignedLxy2)
121 ,fInvmass(p.fInvmass)
122 ,fInvmassSigma(p.fInvmassSigma)
125 ,fNsectrk2prim(p.fNsectrk2prim)
126 ,fVtxchi2Tightcut(p.fVtxchi2Tightcut)
127 ,fVtxchi2Loosecut(p.fVtxchi2Loosecut)
135 fFilter = new AliHFEtrackFilter(*p.fFilter);
138 //_______________________________________________________________________________________________
140 AliHFEsecVtx::operator=(const AliHFEsecVtx &)
143 // Assignment operator
146 AliInfo("Not yet implemented.");
150 //_______________________________________________________________________________________________
151 AliHFEsecVtx::~AliHFEsecVtx()
157 //cout << "Analysis Done." << endl;
161 //__________________________________________
162 void AliHFEsecVtx::Init()
165 // set pdg code and index
170 fParentSelect[0][0] = 411;
171 fParentSelect[0][1] = 421;
172 fParentSelect[0][2] = 431;
173 fParentSelect[0][3] = 4122;
174 fParentSelect[0][4] = 4132;
175 fParentSelect[0][5] = 4232;
176 fParentSelect[0][6] = 4332;
178 fParentSelect[1][0] = 511;
179 fParentSelect[1][1] = 521;
180 fParentSelect[1][2] = 531;
181 fParentSelect[1][3] = 5122;
182 fParentSelect[1][4] = 5132;
183 fParentSelect[1][5] = 5232;
184 fParentSelect[1][6] = 5332;
186 // momentum ranges to apply pt dependent cuts
195 // momentum dependent DCA cut values (preliminary)
203 fFilter = new AliHFEtrackFilter("SecVtxFilter");
204 fFilter->MakeCutStepRecKineITSTPC();
205 fFilter->MakeCutStepPrimary();
208 void AliHFEsecVtx::Process(AliVTrack *signalTrack){
212 //if(signalTrack->Pt() < 1.0) return;
215 AliESDtrack *track = dynamic_cast<AliESDtrack *>(signalTrack);
217 FillHistos(0,track); // wo any cuts
221 AliESDtrack *htrack = 0x0;
223 fFilter->FilterTracks(fESD1);
224 TObjArray *candidates = fFilter->GetFilteredTracks();
225 TIterator *trackIter = candidates->MakeIterator();
226 while((htrack = dynamic_cast<AliESDtrack *>(trackIter->Next()))){
227 if(track->GetID() == htrack->GetID()) continue; // since it is for tagging single electron, don't need additional condition
228 if (htrack->Pt()<1.0) continue;
229 PairAnalysis(track, htrack, htrack->GetID()); // e-h pairing
232 for(int ip=0; ip<HFEpairs()->GetEntriesFast(); ip++){
234 AliHFEpairs *pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ip));
235 //if(!(pair->GetPairCode()>1. && pair->GetPairCode()<4.)) // apply various cuts
236 if(pair->GetKFChi2()>5.) // only apply vertex chi2 cut for the moment
237 HFEpairs()->RemoveAt(ip);
240 HFEpairs()->Compress();
241 if(HFEpairs()->GetEntriesFast()) FillHistos(1,track); // after paired
242 if(HFEpairs()->GetEntriesFast()) RunSECVTX(track); // secondary vertexing with e,h1,h2,.. tracks
243 if(HFEsecvtxs()->GetEntriesFast()) FillHistos(2,track); // after secvtxing
244 for(int ip=0; ip<HFEsecvtxs()->GetEntriesFast(); ip++){
245 AliHFEsecVtxs *secvtx=0x0;
246 secvtx = (AliHFEsecVtxs*) (HFEsecvtxs()->UncheckedAt(ip));
247 // here you apply cuts, then if it doesn't pass the cut, remove it from the HFEsecvtxs()
248 if(!(secvtx->GetInvmass()>2.0 && secvtx->GetInvmass()<5.2) || !(secvtx->GetSignedLxy2()>0.08 && secvtx->GetSignedLxy2()<1.5) || !(secvtx->GetKFIP2()>-0.1 && secvtx->GetKFIP2()<0.1))
249 HFEsecvtxs()->RemoveAt(ip);
252 // fill histos for raw spectra
253 if(HFEsecvtxs()->GetEntriesFast()) FillHistos(3,track); //after secvtx cut
259 //_______________________________________________________________________________________________
260 void AliHFEsecVtx::CreateHistograms(TList * const qaList)
268 fSecVtxList = qaList;
269 fSecVtxList->SetName("SecVtx");
278 fkSourceLabel[kAll]="all";
279 fkSourceLabel[kDirectCharm]="directCharm";
280 fkSourceLabel[kDirectBeauty]="directBeauty";
281 fkSourceLabel[kBeautyCharm]="beauty2charm";
282 fkSourceLabel[kGamma]="gamma";
283 fkSourceLabel[kPi0]="pi0";
284 fkSourceLabel[kElse]="others";
285 fkSourceLabel[kBeautyGamma]="beauty22gamma";
286 fkSourceLabel[kBeautyPi0]="beauty22pi0";
287 fkSourceLabel[kBeautyElse]="beauty22others";
290 TString hnopt="secvtx_";
291 for (Int_t isource = 0; isource < 10; isource++ ){
295 //qaList->AddLast(fSecVtxList);
298 //_______________________________________________________________________________________________
299 void AliHFEsecVtx::GetPrimaryCondition()
302 // get primary characteristics and set
306 AliKFVertex primVtxCopy(*(fESD1->GetPrimaryVertex()));
307 if( primVtxCopy.GetNDF() <1 ) return;
308 fPVx = primVtxCopy.GetX();
309 fPVy = primVtxCopy.GetY();
312 AliKFVertex primVtxCopy(*(fAOD1->GetPrimaryVertex()));
313 if( primVtxCopy.GetNDF() <1 ) return;
314 fPVx = primVtxCopy.GetX();
315 fPVy = primVtxCopy.GetY();
319 //_______________________________________________________________________________________________
320 void AliHFEsecVtx::PairAnalysis(AliVTrack* track1, AliVTrack* track2, Int_t index2)
323 // calculate e-h pair characteristics and tag pair
326 //later consider the below
327 Float_t dca1[2]={-999.,-999.}, dca2[2]={-999.,-999.};
328 Float_t cov1[3]={-999.,-999.,-999.}, cov2[3]={-999.,-999.,-999.};
330 Double_t dca1aod[2]={-999.,-999.}, dca2aod[2]={-999.,-999.};
331 Double_t cov1aod[3]={-999.,-999.,-999.}, cov2aod[3]={-999.,-999.,-999.};
333 if (IsAODanalysis()){
334 const AliAODVertex *primVtx = fAOD1->GetPrimaryVertex();
335 AliESDtrack esdTrk1(track1);
336 AliESDtrack esdTrk2(track2);
337 esdTrk1.PropagateToDCA(primVtx,0.,10000.,dca1aod,cov1aod);
338 esdTrk2.PropagateToDCA(primVtx,0.,10000.,dca2aod,cov2aod);
341 ((AliESDtrack*)track1)->GetImpactParameters(dca1,cov1);
342 ((AliESDtrack*)track2)->GetImpactParameters(dca2,cov2);
345 // apply pt dependent dca cut on hadrons
346 /*for(int ibin=0; ibin<6; ibin++){
347 if((track2->Pt()>fPtRng[ibin] && track2->Pt()<fPtRng[ibin+1]) && TMath::Abs(dca2[0])<fDcaCut[ibin]) return;
350 // get KF particle input pid
351 Int_t pdg1 = GetPDG(track1);
352 Int_t pdg2 = GetPDG(track2);
354 if(pdg1==-1 || pdg2==-1) {
355 //printf("out if considered pid range \n");
359 // create KF particle of pair
360 if(IsAODanalysis()) AliKFParticle::SetField(fAOD1->GetMagneticField());
361 else AliKFParticle::SetField(fESD1->GetMagneticField());
363 AliKFParticle kfTrack[2];
364 kfTrack[0] = AliKFParticle(*track1, pdg1);
365 kfTrack[1] = AliKFParticle(*track2, pdg2);
367 AliKFParticle kfSecondary(kfTrack[0],kfTrack[1]);
369 //secondary vertex point from kf particle
370 Double_t kfx = kfSecondary.GetX();
371 Double_t kfy = kfSecondary.GetY();
372 //Double_t kfz = kfSecondary.GetZ();
374 //momentum at the decay point from kf particle
375 Double_t kfpx = kfSecondary.GetPx();
376 Double_t kfpy = kfSecondary.GetPy();
377 //Double_t kfpz = kfSecondary.GetPz();
380 /* //directly use of ESD vertex
381 const AliESDVertex *pvertex = fESD1->GetPrimaryVertex();
383 pvertex->GetXYZ(xyzVtx);
385 Double_t dx = kfx-xyzVtx[0];
386 Double_t dy = kfy-xyzVtx[1];*/
388 AliKFVertex primVtxCopy(*(fESD1->GetPrimaryVertex()));
389 if( primVtxCopy.GetNDF() <1 ) return;
390 fPVx = primVtxCopy.GetX();
391 fPVy = primVtxCopy.GetY();
393 // printf("esdx= %lf kfx= %lf esdy= %lf kfy= %lf\n",xyzVtx[0],fPVx,xyzVtx[1],fPVy);
395 Double_t dx = kfx-fPVx;
396 Double_t dy = kfy-fPVy;
398 // discriminating variables
399 // invariant mass of the KF particle
400 Double_t invmass = -1;
401 Double_t invmassSigma = -1;
402 kfSecondary.GetMass(invmass,invmassSigma);
404 // chi2 of the KF particle
405 Double_t kfchi2 = -1;
406 if(kfSecondary.GetNDF()>0) kfchi2 = TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
408 // opening angle between two particles in XY plane
409 Double_t phi = kfTrack[0].GetAngleXY(kfTrack[1]);
410 Double_t cosphi = TMath::Cos(phi);
412 // DCA from primary to e-h KF particle (impact parameter of KF particle)
413 Double_t vtx[2]={fPVx, fPVy};
414 Double_t kfip = kfSecondary.GetDistanceFromVertexXY(vtx);
416 // projection of kf vertex vector to the kf momentum direction
417 Double_t signedLxy=-999.;
418 if((dx*kfpx+dy*kfpy)>0) signedLxy = TMath::Sqrt(dx*dx+dy*dy);
419 if((dx*kfpx+dy*kfpy)<0) signedLxy = -1*TMath::Sqrt(dx*dx+dy*dy);
420 //[the other way to think about]
421 //Double_t psqr = kfpx*kfpx+kfpy*kfpy;
422 //if(psqr>0) signedLxy=(dx*kfpx+dy*kfpy)/TMath::Sqrt(psqr);
424 //recalculating primary vertex after removing secvtx tracks --------------------------
426 trkid[0] = track1->GetID();
427 trkid[1] = track2->GetID();
429 RecalcPrimvtx(2, trkid, kfTrack);
430 Double_t dx2 = kfx-fPVx2;
431 Double_t dy2 = kfy-fPVy2;
433 // IP of sec particle recalculated based on recalculated primary vertex
434 Double_t vtx2[2]={fPVx2, fPVy2};
435 Double_t kfip2 = kfSecondary.GetDistanceFromVertexXY(vtx2);
436 // signed Lxy recalculated based on recalculated primary vertex
437 Double_t signedLxy2=-999.;
438 if((dx2*kfpx+dy2*kfpy)>0) signedLxy2 = TMath::Sqrt(dx2*dx2+dy2*dy2);
439 if((dx2*kfpx+dy2*kfpy)<0) signedLxy2 = -1*TMath::Sqrt(dx2*dx2+dy2*dy2);
440 //------------------------------------------------------------------------------------
444 if (HasMCData()) paircode = GetPairCode(track1,track2);
447 hfepair.SetTrkLabel(index2);
448 hfepair.SetInvmass(invmass);
449 hfepair.SetKFChi2(kfchi2);
450 hfepair.SetOpenangle(phi);
451 hfepair.SetCosOpenangle(cosphi);
452 hfepair.SetSignedLxy(signedLxy);
453 hfepair.SetSignedLxy2(signedLxy2);
454 hfepair.SetKFIP(kfip);
455 hfepair.SetKFIP2(kfip2);
456 hfepair.SetPairCode(paircode);
457 AddHFEpairToArray(&hfepair);
460 // fill into container for later QA
468 //if(cov1[0]>0) dataE[6]=Double_t(dca1[0]/cov1[0]);
469 //if(cov2[0]>0) dataE[7]=Double_t(dca2[0]/cov2[0]);
470 //dataE[6]=track1->Pt();
471 //dataE[7]=track2->Pt();
472 //dataE[6]=dca1[0]; //mjtmp
473 //dataE[7]=dca2[0]; //mjtmp
474 //dataE[8]=TMath::Abs(dca1[0]);
475 //dataE[9]=TMath::Abs(dca2[0]);
477 fPairQA->Fill(dataE);
481 //_______________________________________________________________________________________________
482 void AliHFEsecVtx::RunSECVTX(AliVTrack *track)
485 // run secondary vertexing algorithm and do tagging
488 //printf("number of considered pairs= %d\n",HFEpairs()->GetEntriesFast());
489 FindSECVTXCandid(track);
492 //_______________________________________________________________________________________________
493 void AliHFEsecVtx::FindSECVTXCandid(AliVTrack *track)
496 // find secondary vertex candidate and store them into container
499 AliVTrack *htrack[20];
500 //Int_t htracklabel[20];
501 //Int_t paircode[20];
502 //Double_t vtxchi2[20];
503 //Double_t dataE[7]={-999.,-999.,-999.,-999.,-1.,0,0};
505 fVtxchi2Tightcut=3.; // tight cut for pair
506 fVtxchi2Loosecut=5.; // loose cut for secvtx
508 if (HFEpairs()->GetEntriesFast()>20){
509 AliDebug(3, "number of paired hadron is over maximum(20)");
513 // get paired track objects
514 AliHFEpairs *pair=0x0;
515 if (IsAODanalysis()){
516 for (int ip=0; ip<HFEpairs()->GetEntriesFast(); ip++){
517 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ip));
518 //htracklabel[ip] = pair->GetTrkLabel();
519 htrack[ip] = fAOD1->GetTrack(pair->GetTrkLabel());
520 //if(pair->GetPairCode()==2 || pair->GetPairCode()==3) paircode[ip]=1;
521 //else paircode[ip]=0;
522 //vtxchi2[ip] = pair->GetKFChi2();
526 for (int ip=0; ip<HFEpairs()->GetEntriesFast(); ip++){
527 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ip));
528 //htracklabel[ip] = pair->GetTrkLabel();
529 htrack[ip] = fESD1->GetTrack(pair->GetTrkLabel());
530 //if(pair->GetPairCode()==2 || pair->GetPairCode()==3) paircode[ip]=1;
531 //else paircode[ip]=0;
532 //vtxchi2[ip] = pair->GetKFChi2();
536 Int_t nPairs = HFEpairs()->GetEntriesFast();
539 // 1 electron candidate + 1 track
541 if (pair->GetKFChi2() < fVtxchi2Tightcut) { // you can also put single track cut -> here you apply very tight cut for the pair
542 Fill2TrkSECVTX(track, pair);
546 //--------------------------------------------------------------
548 // 1 electron candidate + 2 tracks
550 CalcSECVTXProperty(track, htrack[0], htrack[1]); // calculate secondary vertex property
552 if (fKFchi2 < fVtxchi2Loosecut) { // -> here you apply rather loose cut
553 Fill3TrkSECVTX(track, 0, 1);
555 else{ // if doesn't pass the sec vtx chi2 cut
556 for(int jp=0; jp<2; jp++){
557 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jp));
558 if (pair->GetKFChi2() < fVtxchi2Tightcut){
559 Fill2TrkSECVTX(track, pair);
565 //--------------------------------------------------------------
567 // 1 electron candidate + 3 tracks
569 CalcSECVTXProperty(track, htrack[0], htrack[1], htrack[2]); // calculate secondary vertex property
571 if (fKFchi2 < fVtxchi2Loosecut) {
572 Fill4TrkSECVTX(track, 0, 1, 2);
576 for (int i=0; i<nPairs-1; i++){
577 for (int j=i+1; j<nPairs; j++){
578 CalcSECVTXProperty(track, htrack[i], htrack[j]);
579 if (fKFchi2 < fVtxchi2Loosecut) {
581 Fill3TrkSECVTX(track, i, j);
585 if(!fArethereSecVtx){
586 for(int jp=0; jp<nPairs; jp++){
587 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jp));
588 if (pair->GetKFChi2() < fVtxchi2Tightcut){
589 Fill2TrkSECVTX(track, pair);
596 //--------------------------------------------------------------
598 // 1 electron candidate + more than 3 tracks
601 for (int ih1=0; ih1<nPairs-2; ih1++){
602 for (int ih2=ih1+1; ih2<nPairs-1; ih2++){
603 for (int ih3=ih2+1; ih3<nPairs; ih3++){
604 CalcSECVTXProperty(track, htrack[ih1], htrack[ih2], htrack[ih3]); // calculate secondary vertex property
605 if (fKFchi2 < fVtxchi2Loosecut) {
607 Fill4TrkSECVTX(track, ih1, ih2, ih3);
612 if (!fArethereSecVtx){
614 for (int i=0; i<nPairs-1; i++){
615 for (int j=i+1; j<nPairs; j++){
616 CalcSECVTXProperty(track, htrack[i], htrack[j]);
617 if (fKFchi2 < fVtxchi2Loosecut) {
619 Fill3TrkSECVTX(track, i, j);
624 if (!fArethereSecVtx){
625 for(int jp=0; jp<nPairs; jp++){
626 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jp));
627 if (pair->GetKFChi2() < fVtxchi2Tightcut){
628 Fill2TrkSECVTX(track, pair);
634 //--------------------------------------------------------------
638 //_______________________________________________________________________________________________
639 void AliHFEsecVtx::Fill4TrkSECVTX(AliVTrack* track, Int_t ipair, Int_t jpair, Int_t kpair)
642 // fill 3 tracks' secondary vertex properties
645 Double_t dataE[9]={-999.,-999.,-999.,-999.,-1.,0,0,-999.,-999.};
647 Int_t paircode1 = 0, paircode2 = 0, paircode3 = 0;
648 Int_t htracklabel1 = 0, htracklabel2= 0;
651 AliHFEpairs *pair1=0x0;
652 AliHFEpairs *pair2=0x0;
653 AliHFEpairs *pair3=0x0;
654 pair1 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ipair));
655 pair2 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jpair));
656 pair3 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(kpair));
658 htracklabel1 = pair1->GetTrkLabel();
659 htracklabel2 = pair2->GetTrkLabel();
661 if (pair1->GetPairCode()==2 || pair1->GetPairCode()==3) paircode1=1;
663 if (pair2->GetPairCode()==2 || pair2->GetPairCode()==3) paircode2=1;
665 if (pair3->GetPairCode()==2 || pair3->GetPairCode()==3) paircode3=1;
669 AliHFEsecVtxs hfesecvtx;
670 hfesecvtx.SetTrkLabel1(htracklabel1); // mj: not much meaningful for the moment
671 hfesecvtx.SetTrkLabel2(htracklabel2); // mj: not much meaningful for the moment
672 if(HasMCData()) hfesecvtx.SetMCCode(GetElectronSource(TMath::Abs(track->GetLabel())));
673 hfesecvtx.SetKFChi2(fKFchi2);
674 hfesecvtx.SetInvmass(fInvmass);
675 hfesecvtx.SetSignedLxy(fSignedLxy);
676 hfesecvtx.SetSignedLxy2(fSignedLxy2);
677 hfesecvtx.SetKFIP(fKFip);
678 hfesecvtx.SetKFIP2(fKFip2);
679 AddHFEsecvtxToArray(&hfesecvtx);
686 if(HasMCData()) dataE[4]=GetElectronSource(TMath::Abs(track->GetLabel()));
687 dataE[5]=4; //# of associated tracks
688 if(paircode1 & paircode2 & paircode3) dataE[6]=1;
689 else if(!paircode1 & !paircode2 & !paircode3) dataE[6]=0;
691 dataE[7]=fSignedLxy2;
692 dataE[8]=track->Pt();
693 fSecvtxQA->Fill(dataE);
696 //_______________________________________________________________________________________________
697 void AliHFEsecVtx::Fill3TrkSECVTX(AliVTrack* track, Int_t ipair, Int_t jpair)
700 // fill 3 tracks' secondary vertex properties
703 Double_t dataE[9]={-999.,-999.,-999.,-999.,-1.,0,0,-999.,-999.};
705 Int_t paircode1 = 0, paircode2 = 0;
706 Int_t htracklabel1 = 0, htracklabel2 = 0;
709 AliHFEpairs *pair1=0x0;
710 AliHFEpairs *pair2=0x0;
711 pair1 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ipair));
712 pair2 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jpair));
714 htracklabel1 = pair1->GetTrkLabel();
715 htracklabel2 = pair2->GetTrkLabel();
717 if (pair1->GetPairCode()==2 || pair1->GetPairCode()==3) paircode1=1;
719 if (pair2->GetPairCode()==2 || pair2->GetPairCode()==3) paircode2=1;
723 // fill secondary vertex container
724 AliHFEsecVtxs hfesecvtx;
725 hfesecvtx.SetTrkLabel1(htracklabel1);
726 hfesecvtx.SetTrkLabel2(htracklabel2);
727 if(HasMCData()) hfesecvtx.SetMCCode(GetElectronSource(TMath::Abs(track->GetLabel())));
728 hfesecvtx.SetKFChi2(fKFchi2);
729 hfesecvtx.SetInvmass(fInvmass);
730 hfesecvtx.SetSignedLxy(fSignedLxy);
731 hfesecvtx.SetSignedLxy2(fSignedLxy2);
732 hfesecvtx.SetKFIP(fKFip);
733 hfesecvtx.SetKFIP2(fKFip2);
734 AddHFEsecvtxToArray(&hfesecvtx);
737 // fill debugging THnSparse
742 if(HasMCData()) dataE[4]=GetElectronSource(TMath::Abs(track->GetLabel()));
744 if(paircode1 & paircode2) dataE[6]=1;
745 else if(!paircode1 & !paircode2) dataE[6]=0;
747 dataE[7]=fSignedLxy2;
748 dataE[8]=track->Pt();
749 fSecvtxQA->Fill(dataE);
753 //_______________________________________________________________________________________________
754 void AliHFEsecVtx::Fill2TrkSECVTX(AliVTrack* track, AliHFEpairs *pair)
757 // fill 2 tracks' secondary vertex properties
760 Double_t dataE[9]={-999.,-999.,-999.,-999.,-1.,0,0,-999.,-999.};
763 if (pair->GetPairCode()==2 || pair->GetPairCode()==3) paircode=1;
766 // fill secondary vertex container
767 AliHFEsecVtxs hfesecvtx;
768 hfesecvtx.SetTrkLabel1(pair->GetTrkLabel());
769 hfesecvtx.SetTrkLabel2(-999);
770 if(HasMCData()) hfesecvtx.SetMCCode(GetElectronSource(TMath::Abs(track->GetLabel())));
771 hfesecvtx.SetInvmass(pair->GetInvmass());
772 hfesecvtx.SetKFChi2(pair->GetKFChi2());
773 hfesecvtx.SetSignedLxy(pair->GetSignedLxy());
774 hfesecvtx.SetSignedLxy2(pair->GetSignedLxy2());
775 hfesecvtx.SetKFIP(pair->GetKFIP());
776 hfesecvtx.SetKFIP2(pair->GetKFIP2());
777 AddHFEsecvtxToArray(&hfesecvtx);
780 // fill debugging THnSparse
781 dataE[0]=pair->GetInvmass();
782 dataE[1]=pair->GetKFChi2();
783 dataE[2]=pair->GetSignedLxy();
784 dataE[3]=pair->GetKFIP();
785 if (HasMCData()) dataE[4]=GetElectronSource(TMath::Abs(track->GetLabel()));
786 dataE[5]=2; //# of associated tracks
788 dataE[7]=pair->GetSignedLxy2();
789 dataE[8]=track->Pt();
790 fSecvtxQA->Fill(dataE);
794 //_______________________________________________________________________________________________
795 void AliHFEsecVtx::CalcSECVTXProperty(AliVTrack* track1, AliVTrack* track2, AliVTrack* track3)
798 // calculate secondary vertex properties
801 // get KF particle input pid
802 Int_t pdg1 = GetPDG(track1);
803 Int_t pdg2 = GetPDG(track2);
804 Int_t pdg3 = GetPDG(track3);
806 if(pdg1==-1 || pdg2==-1 || pdg3==-1) {
807 //printf("out if considered pid range \n");
811 // create KF particle of pair
812 if(IsAODanalysis()) AliKFParticle::SetField(fAOD1->GetMagneticField());
813 else AliKFParticle::SetField(fESD1->GetMagneticField());
814 AliKFParticle kfTrack[3];
815 kfTrack[0] = AliKFParticle(*track1, pdg1);
816 kfTrack[1] = AliKFParticle(*track2, pdg2);
817 kfTrack[2] = AliKFParticle(*track3, pdg3);
819 AliKFParticle kfSecondary(kfTrack[0],kfTrack[1],kfTrack[2]);
820 //AliKFParticle kfSecondary(kfTrack1,kfTrack2,kfTrack3);
822 //secondary vertex point from kf particle
823 Double_t kfx = kfSecondary.GetX();
824 Double_t kfy = kfSecondary.GetY();
825 //Double_t kfz = kfSecondary.GetZ();
827 //momentum at the decay point from kf particle
828 Double_t kfpx = kfSecondary.GetPx();
829 Double_t kfpy = kfSecondary.GetPy();
830 //Double_t kfpz = kfSecondary.GetPz();
832 Double_t dx = kfx-fPVx;
833 Double_t dy = kfy-fPVy;
835 // discriminating variables ----------------------------------------------------------
837 if(kfSecondary.GetNDF()>0) fKFchi2 = TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
839 // invariant mass of the KF particle
840 kfSecondary.GetMass(fInvmass,fInvmassSigma);
842 // DCA from primary to e-h KF particle (impact parameter of KF particle)
843 Double_t vtx[2]={fPVx, fPVy};
844 fKFip = kfSecondary.GetDistanceFromVertexXY(vtx);
846 if((dx*kfpx+dy*kfpy)>0) fSignedLxy= TMath::Sqrt(dx*dx+dy*dy);
847 if((dx*kfpx+dy*kfpy)<0) fSignedLxy= -1*TMath::Sqrt(dx*dx+dy*dy);
848 //[the other way to think about] - projection of kf vertex vector to the kf momentum direction
849 //Double_t psqr = kfpx*kfpx+kfpy*kfpy;
850 //if(psqr>0) fSignedLxy=(dx*kfpx+dy*kfpy)/TMath::Sqrt(psqr);
853 //recalculating primary vertex after removing secvtx tracks --------------------------
855 trkid[0] = track1->GetID();
856 trkid[1] = track2->GetID();
857 trkid[2] = track3->GetID();
859 RecalcPrimvtx(3, trkid, kfTrack);
860 Double_t dx2 = kfx-fPVx2;
861 Double_t dy2 = kfy-fPVy2;
863 // IP of sec particle recalculated based on recalculated primary vertex
864 Double_t vtx2[2]={fPVx2, fPVy2};
865 fKFip2 = kfSecondary.GetDistanceFromVertexXY(vtx2);
866 // signed Lxy recalculated based on recalculated primary vertex
867 if((dx2*kfpx+dy2*kfpy)>0) fSignedLxy2= TMath::Sqrt(dx2*dx2+dy2*dy2);
868 if((dx2*kfpx+dy2*kfpy)<0) fSignedLxy2= -1*TMath::Sqrt(dx2*dx2+dy2*dy2);
869 //------------------------------------------------------------------------------------
873 //_______________________________________________________________________________________________
874 void AliHFEsecVtx::CalcSECVTXProperty(AliVTrack* track1, AliVTrack* track2, AliVTrack* track3, AliVTrack* track4)
877 // calculate secondary vertex properties
880 // get KF particle input pid
881 Int_t pdg1 = GetPDG(track1);
882 Int_t pdg2 = GetPDG(track2);
883 Int_t pdg3 = GetPDG(track3);
884 Int_t pdg4 = GetPDG(track4);
886 if(pdg1==-1 || pdg2==-1 || pdg3==-1 || pdg4==-1) {
887 //printf("out if considered pid range \n");
891 // create KF particle of pair
892 if(IsAODanalysis()) AliKFParticle::SetField(fAOD1->GetMagneticField());
893 else AliKFParticle::SetField(fESD1->GetMagneticField());
895 AliKFParticle kfTrack[4];
896 kfTrack[0] = AliKFParticle(*track1, pdg1);
897 kfTrack[1] = AliKFParticle(*track2, pdg2);
898 kfTrack[2] = AliKFParticle(*track3, pdg3);
899 kfTrack[3] = AliKFParticle(*track4, pdg4);
901 AliKFParticle kfSecondary(kfTrack[0],kfTrack[1],kfTrack[2],kfTrack[3]);
903 //secondary vertex point from kf particle
904 Double_t kfx = kfSecondary.GetX();
905 Double_t kfy = kfSecondary.GetY();
906 //Double_t kfz = kfSecondary.GetZ();
908 //momentum at the decay point from kf particle
909 Double_t kfpx = kfSecondary.GetPx();
910 Double_t kfpy = kfSecondary.GetPy();
911 //Double_t kfpz = kfSecondary.GetPz();
913 Double_t dx = kfx-fPVx;
914 Double_t dy = kfy-fPVy;
916 // discriminating variables ----------------------------------------------------------
918 if(kfSecondary.GetNDF()>0) fKFchi2 = TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
920 // invariant mass of the KF particle
921 kfSecondary.GetMass(fInvmass,fInvmassSigma);
923 // DCA from primary to e-h KF particle (impact parameter of KF particle)
924 Double_t vtx[2]={fPVx, fPVy};
925 fKFip = kfSecondary.GetDistanceFromVertexXY(vtx);
927 if((dx*kfpx+dy*kfpy)>0) fSignedLxy= TMath::Sqrt(dx*dx+dy*dy);
928 if((dx*kfpx+dy*kfpy)<0) fSignedLxy= -1*TMath::Sqrt(dx*dx+dy*dy);
929 //[the other way to think about] - projection of kf vertex vector to the kf momentum direction
930 //Double_t psqr = kfpx*kfpx+kfpy*kfpy;
931 //if(psqr>0) fSignedLxy=(dx*kfpx+dy*kfpy)/TMath::Sqrt(psqr);
933 //recalculating primary vertex after removing secvtx tracks --------------------------
935 trkid[0] = track1->GetID();
936 trkid[1] = track2->GetID();
937 trkid[2] = track3->GetID();
938 trkid[3] = track4->GetID();
940 RecalcPrimvtx(4, trkid, kfTrack);
941 Double_t dx2 = kfx-fPVx2;
942 Double_t dy2 = kfy-fPVy2;
944 // IP of sec particle recalculated based on recalculated primary vertex
945 Double_t vtx2[2]={fPVx2, fPVy2};
946 fKFip2 = kfSecondary.GetDistanceFromVertexXY(vtx2);
947 // signed Lxy recalculated based on recalculated primary vertex
948 if((dx2*kfpx+dy2*kfpy)>0) fSignedLxy2= TMath::Sqrt(dx2*dx2+dy2*dy2);
949 if((dx2*kfpx+dy2*kfpy)<0) fSignedLxy2= -1*TMath::Sqrt(dx2*dx2+dy2*dy2);
950 //------------------------------------------------------------------------------------
954 //_______________________________________________________________________________________________
955 void AliHFEsecVtx::RecalcPrimvtx(Int_t nkftrk, const Int_t * const trkid, const AliKFParticle * const kftrk){
957 // reccalculate primary vertex after removing considering track in the calculation
960 const AliESDVertex *primvtx = fESD1->GetPrimaryVertex();
962 AliKFVertex kfESDprimary;
963 Int_t n = primvtx->GetNIndices();
968 if (n>0 && primvtx->GetStatus()){
969 kfESDprimary = AliKFVertex(*primvtx);
970 UShort_t *priIndex = primvtx->GetIndices();
971 for(Int_t j=0; j<nkftrk; j++){
972 for (Int_t i=0;i<n;i++){
973 Int_t idx = Int_t(priIndex[i]);
974 if (idx == trkid[j]){
975 kfESDprimary -= kftrk[j];
982 fPVx2 = kfESDprimary.GetX();
983 fPVy2 = kfESDprimary.GetY();
987 //_______________________________________________________________________________________________
988 Int_t AliHFEsecVtx::GetMCPID(const AliESDtrack *track)
994 AliMCParticle *mctrack = NULL;
995 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(track->GetLabel()))))) return 0;
996 TParticle *mcpart = mctrack->Particle();
998 if ( !mcpart ) return 0;
999 Int_t pdgCode = mcpart->GetPdgCode();
1004 //_______________________________________________________________________________________________
1005 Int_t AliHFEsecVtx::GetPairOriginESD(AliESDtrack* trk1, AliESDtrack* trk2)
1008 // return pdg code of the origin(source) of the pair
1011 // ---*---*---*-----ancester A----- track1
1014 // => if they originated from same ancester,
1015 // then return "the absolute value of pdg code of ancester A"
1017 // ---*---*---B hadron-----ancester A----- track1
1020 // => if they originated from same ancester, and this ancester originally comes from B hadrons
1021 // then return -1*"the absolute value of pdg code of ancester A"
1023 // caution : it can also return parton pdg code if it originated from same string or gluon spliting.
1026 if (trk1->GetLabel()<0 || trk2->GetLabel()<0) return 0;
1028 AliMCParticle *mctrack = NULL;
1029 AliMCParticle *mctrack1 = NULL;
1030 AliMCParticle *mctrack2 = NULL;
1031 if(!(mctrack1 = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(trk1->GetLabel()))))) return 0;
1032 if(!(mctrack2 = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(trk2->GetLabel()))))) return 0;
1033 TParticle *part1 = mctrack1->Particle();
1034 TParticle *part2 = mctrack2->Particle();
1036 TParticle* part2cp = part2;
1037 if (!(part1) || !(part2)) return 0;
1041 //if the two tracks' mother's label is same, get the mother info
1042 //in case of charm, check if it originated from beauty
1043 for (Int_t i=0; i<10; i++){ //check up to 10 ancesters
1044 Int_t label1 = part1->GetFirstMother();
1045 if (label1 < 0) return 0;
1047 for (Int_t j=0; j<10; j++){ //check up to 10 ancesters
1048 Int_t label2 = part2->GetFirstMother();
1049 if (label2 < 0) break;
1051 if (label1 == label2){ //check if two tracks are originated from same mother
1052 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(label2))))) return 0;
1053 TParticle* commonmom = mctrack->Particle();
1055 srcpdg = abs(commonmom->GetPdgCode());
1057 //check ancester to see if it is originally from beauty
1058 for (Int_t k=0; k<10; k++){ //check up to 10 ancesters
1059 Int_t ancesterlabel = commonmom->GetFirstMother();
1060 if (ancesterlabel < 0) return srcpdg; // if there is no more commonancester, return commonmom's pdg
1062 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(ancesterlabel))))) return 0;
1063 TParticle* commonancester = mctrack->Particle();
1065 Int_t ancesterpdg = abs(commonancester->GetPdgCode());
1067 for (Int_t l=0; l<fNparents; l++){
1068 if (abs(ancesterpdg)==fParentSelect[1][l]){
1069 srcpdg = -1*srcpdg; //multiply -1 for hadron from bottom
1073 commonmom = commonancester;
1076 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(label2))))) return 0;
1077 part2 = mctrack->Particle(); //if their mother is different, go to earlier generation of 2nd particle
1079 if (!(part2)) break;
1081 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(label1))))) return 0;
1082 part1 = mctrack->Particle(); //if their mother is different, go to earlier generation of 1st particle
1084 if (!(part1)) return 0;
1090 //_______________________________________________________________________________________________
1091 Int_t AliHFEsecVtx::GetPairOriginAOD(AliAODTrack* trk1, AliAODTrack* trk2)
1095 // return pdg code of the origin(source) of the pair
1098 // ---*---*---*-----ancester A----- track1
1101 // => if they originated from same ancester,
1102 // then return "the absolute value of pdg code of ancester A"
1104 // ---*---*---B hadron-----ancester A----- track1
1107 // => if they originated from same ancester, and this ancester originally comes from B hadrons
1108 // then return -1*"the absolute value of pdg code of ancester A"
1110 // caution : it can also return parton pdg code if it originated from same string or gluon spliting.
1113 if (trk1->GetLabel()<0 || trk2->GetLabel()<0) return 0;
1114 AliAODMCParticle *part1 = (AliAODMCParticle*)fMCArray->At(trk1->GetLabel());
1115 AliAODMCParticle *part2 = (AliAODMCParticle*)fMCArray->At(trk2->GetLabel());
1116 AliAODMCParticle *part2cp = part2;
1117 if (!(part1) || !(part2)) return 0;
1121 //if the two tracks' mother's label is same, get the mother info
1122 //in case of charm, check if it originated from beauty
1123 for (Int_t i=0; i<10; i++){ //check up to 10 ancesters
1124 Int_t label1 = part1->GetMother();
1125 if (label1 < 0) return 0;
1127 for (Int_t j=0; j<10; j++){ //check up to 10 ancesters
1128 Int_t label2 = part2->GetMother();
1129 if (label2 < 0) return 0;
1131 if (label1 == label2){ //check if two tracks are originated from same mother
1132 AliAODMCParticle *commonmom = (AliAODMCParticle*)fMCArray->At(label1);
1133 srcpdg = abs(commonmom->GetPdgCode());
1135 //check ancester to see if it is originally from beauty
1136 for (Int_t k=0; k<10; k++){ //check up to 10 ancesters
1137 Int_t ancesterlabel = commonmom->GetMother();
1138 if (ancesterlabel < 0) return srcpdg; // if there is no more commonancester, return commonmom's pdg
1140 AliAODMCParticle *commonancester = (AliAODMCParticle*)fMCArray->At(ancesterlabel);
1141 Int_t ancesterpdg = abs(commonancester->GetPdgCode());
1143 for (Int_t l=0; l<fNparents; l++){
1144 if (abs(ancesterpdg)==fParentSelect[1][l]){
1145 srcpdg = -1*srcpdg; //multiply -1 for charm from bottom
1149 commonmom = commonancester;
1152 part2 = (AliAODMCParticle*)fMCArray->At(label2); //if their mother is different, go to earlier generation of 2nd particle
1153 if (!(part2)) break;
1155 part1 = (AliAODMCParticle*)fMCArray->At(label1); //if their mother is different, go to earlier generation of 2nd particle
1157 if (!(part1)) return 0;
1163 //_______________________________________________________________________________________________
1164 Int_t AliHFEsecVtx::GetPairCode(const AliVTrack* const trk1, const AliVTrack* const trk2)
1167 // return pair code which is predefinded as:
1168 // kDirectCharm, kDirectBeauty, kBeautyCharm, kGamma, kPi0,
1169 // kElse, kBeautyGamma, kBeautyPi0, kBeautyElse
1173 Int_t srccode = kElse;
1175 if(IsAODanalysis()) srcpdg = GetPairOriginAOD((AliAODTrack*)trk1,(AliAODTrack*)trk2);
1176 else srcpdg = GetPairOriginESD((AliESDtrack*)trk1,(AliESDtrack*)trk2);
1178 if (srcpdg < 0) srccode = kBeautyElse;
1179 for (Int_t i=0; i<fNparents; i++){
1180 if (abs(srcpdg)==fParentSelect[0][i]) {
1181 if (srcpdg>0) srccode = kDirectCharm;
1182 if (srcpdg<0) srccode = kBeautyCharm;
1184 if (abs(srcpdg)==fParentSelect[1][i]) {
1185 if (srcpdg>0) srccode = kDirectBeauty;
1186 if (srcpdg<0) return kElse;
1189 if (srcpdg == 22) srccode = kGamma;
1190 if (srcpdg == -22) srccode = kBeautyGamma;
1191 if (srcpdg == 111) srccode = kPi0;
1192 if (srcpdg == -111) srccode = kBeautyPi0;
1197 //_______________________________________________________________________________________________
1198 Int_t AliHFEsecVtx::GetElectronSource(Int_t iTrack)
1201 // return decay electron's origin
1205 AliDebug(1, "Stack label is negative, return\n");
1209 AliMCParticle *mctrack = NULL;
1210 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(iTrack))))) return -1;
1211 TParticle *mcpart = mctrack->Particle();
1214 AliDebug(1, "no mc particle, return\n");
1218 if ( abs(mcpart->GetPdgCode()) != 11 ) return kMisID;
1220 // if ( abs(mcpart->GetPdgCode()) != 11 ) return -1; // check if it is electron !
1222 Int_t iLabel = mcpart->GetFirstMother();
1224 AliDebug(1, "Stack label is negative, return\n");
1229 Bool_t isFinalOpenCharm = kFALSE;
1231 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(iLabel))))) return -1;
1232 TParticle *partMother = mctrack->Particle();
1234 Int_t maPdgcode = partMother->GetPdgCode();
1236 // if the mother is charmed hadron
1237 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
1239 for (Int_t i=0; i<fNparents; i++){
1240 if (abs(maPdgcode)==fParentSelect[0][i]){
1241 isFinalOpenCharm = kTRUE;
1244 if (!isFinalOpenCharm) return -1;
1246 // iterate until you find B hadron as a mother or become top ancester
1247 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1249 Int_t jLabel = partMother->GetFirstMother();
1251 origin = kDirectCharm;
1254 if (jLabel < 0){ // safety protection
1255 AliDebug(1, "Stack label is negative, return\n");
1259 // if there is an ancester
1260 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1261 TParticle *grandMa = mctrack->Particle();
1263 Int_t grandMaPDG = grandMa->GetPdgCode();
1265 for (Int_t j=0; j<fNparents; j++){
1266 if (abs(grandMaPDG)==fParentSelect[1][j]){
1267 origin = kBeautyCharm;
1272 partMother = grandMa;
1273 } // end of iteration
1275 else if ( int(abs(maPdgcode)/100.) == kBeauty || int(abs(maPdgcode)/1000.) == kBeauty ) {
1276 for (Int_t i=0; i<fNparents; i++){
1277 if (abs(maPdgcode)==fParentSelect[1][i]){
1278 origin = kDirectBeauty;
1284 //============ gamma ================
1285 else if ( abs(maPdgcode) == 22 ) {
1288 // iterate until you find B hadron as a mother or become top ancester
1289 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1291 Int_t jLabel = partMother->GetFirstMother();
1296 if (jLabel < 0){ // safety protection
1297 AliDebug(1, "Stack label is negative, return\n");
1301 // if there is an ancester
1302 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1303 TParticle *grandMa = mctrack->Particle();
1305 Int_t grandMaPDG = grandMa->GetPdgCode();
1307 for (Int_t j=0; j<fNparents; j++){
1308 if (abs(grandMaPDG)==fParentSelect[1][j]){
1309 origin = kBeautyGamma;
1314 partMother = grandMa;
1315 } // end of iteration
1320 //============ pi0 ================
1321 else if ( abs(maPdgcode) == 111 ) {
1324 // iterate until you find B hadron as a mother or become top ancester
1325 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1327 Int_t jLabel = partMother->GetFirstMother();
1332 if (jLabel < 0){ // safety protection
1333 AliDebug(1, "Stack label is negative, return\n");
1337 // if there is an ancester
1338 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1339 TParticle *grandMa = mctrack->Particle();
1341 Int_t grandMaPDG = grandMa->GetPdgCode();
1343 for (Int_t j=0; j<fNparents; j++){
1344 if (abs(grandMaPDG)==fParentSelect[1][j]){
1345 origin = kBeautyPi0;
1350 partMother = grandMa;
1351 } // end of iteration
1358 // iterate until you find B hadron as a mother or become top ancester
1359 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1361 Int_t jLabel = partMother->GetFirstMother();
1366 if (jLabel < 0){ // safety protection
1367 AliDebug(1, "Stack label is negative, return\n");
1371 // if there is an ancester
1372 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1373 TParticle *grandMa = mctrack->Particle();
1375 Int_t grandMaPDG = grandMa->GetPdgCode();
1377 for (Int_t j=0; j<fNparents; j++){
1378 if (abs(grandMaPDG)==fParentSelect[1][j]){
1379 origin = kBeautyElse;
1384 partMother = grandMa;
1385 } // end of iteration
1391 //_______________________________________________________________________________________________
1392 Int_t AliHFEsecVtx::GetPDG(AliVTrack *track)
1395 // get KF particle input pdg for mass hypothesis
1400 if (fUseMCPID && HasMCData()){
1401 pdgCode = GetMCPDG(track);
1406 GetESDPID((AliESDtrack*)track, pid, prob);
1408 case 0: pdgCode = 11; break;
1409 case 1: pdgCode = 13; break;
1410 case 2: pdgCode = 211; break;
1411 case 3: pdgCode = 321; break;
1412 case 4: pdgCode = 2212; break;
1413 default: pdgCode = -1;
1417 Int_t pid = ((AliAODTrack*)track)->GetMostProbablePID();
1419 case 0: pdgCode = 11; break;
1420 case 1: pdgCode = 13; break;
1421 case 2: pdgCode = 211; break;
1422 case 3: pdgCode = 321; break;
1423 case 4: pdgCode = 2212; break;
1424 default: pdgCode = -1;
1431 //_______________________________________________________________________________________________
1432 Int_t AliHFEsecVtx::GetMCPDG(const AliVTrack *track)
1435 // return mc pdg code
1438 Int_t label = TMath::Abs(track->GetLabel());
1440 AliMCParticle *mctrack = NULL;
1442 if (IsAODanalysis()) {
1443 AliAODMCParticle *mcpart = (AliAODMCParticle*)fMCArray->At(label);
1444 if ( !mcpart ) return 0;
1445 pdgCode = mcpart->GetPdgCode();
1448 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(label))))) return 0;
1449 TParticle *mcpart = mctrack->Particle();
1451 if ( !mcpart ) return 0;
1452 pdgCode = mcpart->GetPdgCode();
1458 //______________________________________________________________________________
1459 void AliHFEsecVtx::GetESDPID(AliESDtrack *track, Int_t &recpid, Double_t &recprob)
1462 // calculate likehood for esd pid
1471 Double_t probability[5];
1473 // get probability of the diffenrent particle types
1474 track->GetESDpid(probability);
1476 // find most probable particle in ESD pid
1477 // 0:Electron - 1:Muon - 2:Pion - 3:Kaon - 4:Proton
1478 ipid = TMath::LocMax(5,probability);
1479 max = TMath::MaxElement(5,probability);
1485 //_____________________________________________________________________________
1486 void AliHFEsecVtx::AddHFEpairToArray(const AliHFEpairs* const pair)
1489 // Add a HFE pair to the array
1492 Int_t n = HFEpairs()->GetEntriesFast();
1493 if(n!=fNoOfHFEpairs)AliError(Form("fNoOfHFEpairs != HFEpairs()->GetEntriesFast %i != %i \n", fNoOfHFEpairs, n));
1494 new((*HFEpairs())[n]) AliHFEpairs(*pair);
1497 //_____________________________________________________________________________
1498 TClonesArray *AliHFEsecVtx::HFEpairs()
1501 // Returns the list of HFE pairs
1505 fHFEpairs = new TClonesArray("AliHFEpairs", 200);
1510 //_____________________________________________________________________________
1511 void AliHFEsecVtx::DeleteHFEpairs()
1514 // Delete the list of HFE pairs
1518 fHFEpairs->Delete();
1523 //_____________________________________________________________________________
1524 void AliHFEsecVtx::InitHFEpairs()
1527 // Initialization should be done before make all possible pairs for a given electron candidate
1533 //_____________________________________________________________________________
1534 void AliHFEsecVtx::AddHFEsecvtxToArray(const AliHFEsecVtxs* const secvtx)
1537 // Add a HFE secondary vertex to the array
1540 Int_t n = HFEsecvtxs()->GetEntriesFast();
1541 if(n!=fNoOfHFEsecvtxs)AliError(Form("fNoOfHFEsecvtxs != HFEsecvtxs()->GetEntriesFast %i != %i \n", fNoOfHFEsecvtxs, n));
1542 new((*HFEsecvtxs())[n]) AliHFEsecVtxs(*secvtx);
1545 //_____________________________________________________________________________
1546 TClonesArray *AliHFEsecVtx::HFEsecvtxs()
1549 // Returns the list of HFE secvtx
1553 fHFEsecvtxs = new TClonesArray("AliHFEsecVtxs", 200);
1558 //_____________________________________________________________________________
1559 void AliHFEsecVtx::DeleteHFEsecvtxs()
1562 // Delete the list of HFE pairs
1566 fHFEsecvtxs->Delete();
1567 //delete fHFEsecvtx;
1571 //_____________________________________________________________________________
1572 void AliHFEsecVtx::InitHFEsecvtxs()
1575 // Initialization should be done
1578 fNoOfHFEsecvtxs = 0;
1581 //____________________________________________________________
1582 void AliHFEsecVtx::MakeContainer(){
1588 const Int_t nDimPair=6;
1589 Int_t nBinPair[nDimPair] = {200, 500, 314, 2000, 2000, 13};
1590 //Int_t nBinPair[nDimPair] = {200, 500, 314, 2000, 2000, 13, 60, 60, 2000, 2000};
1591 const Double_t kInvmassmin = 0., kInvmassmax = 20.;
1592 const Double_t kKFChi2min = 0, kKFChi2max= 50;
1593 const Double_t kOpenanglemin = 0, kOpenanglemax = 3.14;
1594 const Double_t kSignedLxymin = -10, kSignedLxymax= 10;
1595 const Double_t kKFIPmin = -10, kKFIPmax= 10;
1596 const Double_t kPairCodemin = -1, kPairCodemax= 12;
1597 //const Double_t kPtmin = 0, kPtmax= 30;
1598 //const Double_t kDCAsigmin = -5, kDCAsigmax= 5;
1600 Double_t* binEdgesPair[nDimPair];
1601 for(Int_t ivar = 0; ivar < nDimPair; ivar++)
1602 binEdgesPair[ivar] = new Double_t[nBinPair[ivar] + 1];
1604 for(Int_t i=0; i<=nBinPair[0]; i++) binEdgesPair[0][i]=(Double_t)kInvmassmin + (kInvmassmax - kInvmassmin)/nBinPair[0]*(Double_t)i;
1605 for(Int_t i=0; i<=nBinPair[1]; i++) binEdgesPair[1][i]=(Double_t)kKFChi2min + (kKFChi2max - kKFChi2min)/nBinPair[1]*(Double_t)i;
1606 for(Int_t i=0; i<=nBinPair[2]; i++) binEdgesPair[2][i]=(Double_t)kOpenanglemin + (kOpenanglemax - kOpenanglemin)/nBinPair[2]*(Double_t)i;
1607 for(Int_t i=0; i<=nBinPair[3]; i++) binEdgesPair[3][i]=(Double_t)kSignedLxymin + (kSignedLxymax - kSignedLxymin)/nBinPair[3]*(Double_t)i;
1608 for(Int_t i=0; i<=nBinPair[4]; i++) binEdgesPair[4][i]=(Double_t)kKFIPmin + (kKFIPmax - kKFIPmin)/nBinPair[4]*(Double_t)i;
1609 for(Int_t i=0; i<=nBinPair[5]; i++) binEdgesPair[5][i]=(Double_t)kPairCodemin + (kPairCodemax - kPairCodemin)/nBinPair[5]*(Double_t)i;
1610 //for(Int_t i=0; i<=nBinPair[6]; i++) binEdgesPair[6][i]=(Double_t)kPtmin + (kPtmax - kPtmin)/nBinPair[6]*(Double_t)i;
1611 //for(Int_t i=0; i<=nBinPair[7]; i++) binEdgesPair[7][i]=binEdgesPair[6][i];
1612 //for(Int_t i=0; i<=nBinPair[6]; i++) binEdgesPair[6][i]=(Double_t)kDCAsigmin + (kDCAsigmax - kDCAsigmin)/nBinPair[6]*(Double_t)i;
1613 //for(Int_t i=0; i<=nBinPair[7]; i++) binEdgesPair[7][i]=binEdgesPair[6][i];
1615 fPairQA = new THnSparseF("pairQA", "QA for Pair; invmass[GeV/c^2]; KF chi2; opening angle; signed Lxy; KF ip; pair code; dca1; dca2", nDimPair, nBinPair);
1616 //fPairQA = new THnSparseF("pairQA", "QA for Pair; invmass[GeV/c^2]; KF chi2; opening angle; signed Lxy; KF ip; pair code; pt1; pt2; dca1; dca2", nDimPair, nBinPair);
1617 for(Int_t idim = 0; idim < nDimPair; idim++){
1618 fPairQA->SetBinEdges(idim, binEdgesPair[idim]);
1621 fSecVtxList->AddAt(fPairQA,0);
1623 const Int_t nDimSecvtx=9;
1624 Double_t* binEdgesSecvtx[nDimSecvtx];
1625 Int_t nBinSecvtx[nDimSecvtx] = {200, 500, 2000, 2000, 13, 10, 4, 2000, 500};
1626 const Double_t kNtrksmin = 0, kNtrksmax= 10;
1627 const Double_t kTrueBmin = 0, kTrueBmax= 4;
1628 const Double_t kPtmin = 0, kPtmax= 50;
1629 for(Int_t ivar = 0; ivar < nDimSecvtx; ivar++)
1630 binEdgesSecvtx[ivar] = new Double_t[nBinSecvtx[ivar] + 1];
1632 for(Int_t i=0; i<=nBinSecvtx[0]; i++) binEdgesSecvtx[0][i]=binEdgesPair[0][i];
1633 for(Int_t i=0; i<=nBinSecvtx[1]; i++) binEdgesSecvtx[1][i]=binEdgesPair[1][i];
1634 for(Int_t i=0; i<=nBinSecvtx[2]; i++) binEdgesSecvtx[2][i]=binEdgesPair[3][i];
1635 for(Int_t i=0; i<=nBinSecvtx[3]; i++) binEdgesSecvtx[3][i]=binEdgesPair[4][i];
1636 for(Int_t i=0; i<=nBinSecvtx[4]; i++) binEdgesSecvtx[4][i]=binEdgesPair[5][i];
1637 for(Int_t i=0; i<=nBinSecvtx[5]; i++) binEdgesSecvtx[5][i]=(Double_t)kNtrksmin + (kNtrksmax - kNtrksmin)/nBinSecvtx[5]*(Double_t)i;
1638 for(Int_t i=0; i<=nBinSecvtx[6]; i++) binEdgesSecvtx[6][i]=(Double_t)kTrueBmin + (kTrueBmax - kTrueBmin)/nBinSecvtx[6]*(Double_t)i;
1639 for(Int_t i=0; i<=nBinSecvtx[7]; i++) binEdgesSecvtx[7][i]=binEdgesPair[3][i];
1640 for(Int_t i=0; i<=nBinSecvtx[8]; i++) binEdgesSecvtx[8][i]=(Double_t)kPtmin + (kPtmax - kPtmin)/nBinSecvtx[8]*(Double_t)i;
1642 fSecvtxQA = new THnSparseF("secvtxQA", "QA for Secvtx; invmass[GeV/c^2]; KF chi2; signed Lxy; KF ip; pair code; n tracks ", nDimSecvtx, nBinSecvtx);
1643 for(Int_t idim = 0; idim < nDimSecvtx; idim++){
1644 fSecvtxQA->SetBinEdges(idim, binEdgesSecvtx[idim]);
1647 fSecVtxList->AddAt(fSecvtxQA,1);
1649 for(Int_t ivar = 0; ivar < nDimPair; ivar++)
1650 delete binEdgesPair[ivar];
1651 for(Int_t ivar = 0; ivar < nDimSecvtx; ivar++)
1652 delete binEdgesSecvtx[ivar];
1655 //____________________________________________________________
1656 void AliHFEsecVtx::MakeHistos(Int_t step){
1662 TString hname=Form("step%d",step);
1665 const Double_t kPtbound[2] = {0.1, 20.};
1667 iBin[0] = 44; // bins in pt
1668 Double_t* binEdges[1];
1669 binEdges[0] = AliHFEtools::MakeLogarithmicBinning(iBin[0], kPtbound[0], kPtbound[1]);
1671 fSecVtxList->AddAt(new TH1F(hname+"taggedElec", "pT of e", iBin[0],binEdges[0]), step);
1672 fSecVtxList->AddAt(new TH1F(hname+"charmElec", "pT of e", iBin[0],binEdges[0]), step+1);
1673 fSecVtxList->AddAt(new TH1F(hname+"beautyElec", "pT of e", iBin[0],binEdges[0]), step+2);
1674 fSecVtxList->AddAt(new TH1F(hname+"conversionElec", "pT of e", iBin[0],binEdges[0]), step+3);
1675 fSecVtxList->AddAt(new TH1F(hname+"ebgElec", "pT of e", iBin[0],binEdges[0]), step+4);
1676 fSecVtxList->AddAt(new TH1F(hname+"hcontaminElec", "pT of e", iBin[0],binEdges[0]), step+5);
1677 fSecVtxList->AddAt(new TH1F(hname+"elseElec", "pT of e", iBin[0],binEdges[0]), step+6);
1680 //____________________________________________________________
1681 void AliHFEsecVtx::FillHistos(Int_t step, const AliESDtrack *track){
1689 AliMCParticle *mctrack = NULL;
1690 TParticle* mcpart = NULL;
1692 (dynamic_cast<TH1F *>(fSecVtxList->At(step)))->Fill(track->Pt()); // electrons tagged
1695 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(track->GetLabel()))))) return;
1696 mcpart = mctrack->Particle();
1698 Int_t esource=fMCQA->GetElecSource(mcpart);
1700 (dynamic_cast<TH1F *>(fSecVtxList->At(step+1)))->Fill(mcpart->Pt()); //charm
1702 else if(esource==2 || esource==3) {
1703 (dynamic_cast<TH1F *>(fSecVtxList->At(step+2)))->Fill(mcpart->Pt()); //beauty
1705 else if(esource==4) {
1706 (dynamic_cast<TH1F *>(fSecVtxList->At(step+3)))->Fill(mcpart->Pt()); //conversion
1708 else if(esource==7) {
1709 (dynamic_cast<TH1F *>(fSecVtxList->At(step+5)))->Fill(mcpart->Pt()); //contamination
1711 else if(!(esource<0)) {
1712 (dynamic_cast<TH1F *>(fSecVtxList->At(step+4)))->Fill(mcpart->Pt()); //e backgrounds
1715 (dynamic_cast<TH1F *>(fSecVtxList->At(step+6)))->Fill(mcpart->Pt()); //something else?