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 **************************************************************************/
19 // Secondary vertexing construction Class
20 // Construct secondary vertex from Beauty hadron with electron and
21 // hadrons, then apply selection criteria
24 // MinJung Kweon <minjung@physi.uni-heidelberg.de>
28 #include <TIterator.h>
29 #include <TParticle.h>
31 #include <AliESDVertex.h>
32 #include <AliESDEvent.h>
33 #include <AliAODEvent.h>
34 #include <AliVTrack.h>
35 #include <AliESDtrack.h>
36 #include <AliAODTrack.h>
37 #include "AliHFEsecVtx.h"
38 #include <AliKFParticle.h>
39 #include <AliKFVertex.h>
41 #include <AliMCEvent.h>
42 #include <AliAODMCParticle.h>
43 #include "AliHFEpairs.h"
44 #include "AliHFEsecVtxs.h"
45 #include "AliHFEtrackFilter.h"
46 #include "AliHFEmcQA.h"
47 #include "AliHFEtools.h"
49 ClassImp(AliHFEsecVtx)
51 //_______________________________________________________________________________________________
52 AliHFEsecVtx::AliHFEsecVtx():
90 // Default constructor
96 //_______________________________________________________________________________________________
97 AliHFEsecVtx::AliHFEsecVtx(const AliHFEsecVtx &p):
104 ,fUseMCPID(p.fUseMCPID)
106 ,fNparents(p.fNparents)
110 ,fNoOfHFEpairs(p.fNoOfHFEpairs)
111 ,fNoOfHFEsecvtxs(p.fNoOfHFEsecvtxs)
112 ,fArethereSecVtx(p.fArethereSecVtx)
121 ,fSignedLxy(p.fSignedLxy)
122 ,fSignedLxy2(p.fSignedLxy2)
124 ,fInvmass(p.fInvmass)
125 ,fInvmassSigma(p.fInvmassSigma)
128 ,fNsectrk2prim(p.fNsectrk2prim)
129 ,fVtxchi2Tightcut(p.fVtxchi2Tightcut)
130 ,fVtxchi2Loosecut(p.fVtxchi2Loosecut)
138 fFilter = new AliHFEtrackFilter(*p.fFilter);
141 //_______________________________________________________________________________________________
143 AliHFEsecVtx::operator=(const AliHFEsecVtx &)
146 // Assignment operator
149 AliInfo("Not yet implemented.");
153 //_______________________________________________________________________________________________
154 AliHFEsecVtx::~AliHFEsecVtx()
160 //cout << "Analysis Done." << endl;
164 //__________________________________________
165 void AliHFEsecVtx::Init()
168 // set pdg code and index
173 fParentSelect[0][0] = 411;
174 fParentSelect[0][1] = 421;
175 fParentSelect[0][2] = 431;
176 fParentSelect[0][3] = 4122;
177 fParentSelect[0][4] = 4132;
178 fParentSelect[0][5] = 4232;
179 fParentSelect[0][6] = 4332;
181 fParentSelect[1][0] = 511;
182 fParentSelect[1][1] = 521;
183 fParentSelect[1][2] = 531;
184 fParentSelect[1][3] = 5122;
185 fParentSelect[1][4] = 5132;
186 fParentSelect[1][5] = 5232;
187 fParentSelect[1][6] = 5332;
189 // momentum ranges to apply pt dependent cuts
198 // momentum dependent DCA cut values (preliminary)
206 fFilter = new AliHFEtrackFilter("SecVtxFilter");
207 fFilter->MakeCutStepRecKineITSTPC();
208 fFilter->MakeCutStepPrimary();
211 void AliHFEsecVtx::Process(AliVTrack *signalTrack){
215 //if(signalTrack->Pt() < 1.0) return;
218 AliESDtrack *track = dynamic_cast<AliESDtrack *>(signalTrack);
221 AliDebug(1, "no esd track pointer, return\n");
225 FillHistos(0,track); // wo any cuts
229 AliESDtrack *htrack = 0x0;
231 fFilter->FilterTracks(fESD1);
232 TObjArray *candidates = fFilter->GetFilteredTracks();
233 TIterator *trackIter = candidates->MakeIterator();
234 while((htrack = dynamic_cast<AliESDtrack *>(trackIter->Next()))){
235 if(track->GetID() == htrack->GetID()) continue; // since it is for tagging single electron, don't need additional condition
236 if (htrack->Pt()<1.0) continue;
237 PairAnalysis(track, htrack, htrack->GetID()); // e-h pairing
240 for(int ip=0; ip<HFEpairs()->GetEntriesFast(); ip++){
242 AliHFEpairs *pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ip));
243 //if(!(pair->GetPairCode()>1. && pair->GetPairCode()<4.)) // apply various cuts
244 if(pair->GetKFChi2()>5.) // only apply vertex chi2 cut for the moment
245 HFEpairs()->RemoveAt(ip);
248 HFEpairs()->Compress();
249 if(HFEpairs()->GetEntriesFast()) FillHistos(1,track); // after paired
250 if(HFEpairs()->GetEntriesFast()) RunSECVTX(track); // secondary vertexing with e,h1,h2,.. tracks
251 if(HFEsecvtxs()->GetEntriesFast()) FillHistos(2,track); // after secvtxing
252 for(int ip=0; ip<HFEsecvtxs()->GetEntriesFast(); ip++){
253 AliHFEsecVtxs *secvtx=0x0;
254 secvtx = (AliHFEsecVtxs*) (HFEsecvtxs()->UncheckedAt(ip));
255 // here you apply cuts, then if it doesn't pass the cut, remove it from the HFEsecvtxs()
256 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))
257 HFEsecvtxs()->RemoveAt(ip);
260 // fill histos for raw spectra
261 if(HFEsecvtxs()->GetEntriesFast()) FillHistos(3,track); //after secvtx cut
267 //_______________________________________________________________________________________________
268 void AliHFEsecVtx::CreateHistograms(TList * const qaList)
276 fSecVtxList = qaList;
277 fSecVtxList->SetName("SecVtx");
286 fkSourceLabel[kAll]="all";
287 fkSourceLabel[kDirectCharm]="directCharm";
288 fkSourceLabel[kDirectBeauty]="directBeauty";
289 fkSourceLabel[kBeautyCharm]="beauty2charm";
290 fkSourceLabel[kGamma]="gamma";
291 fkSourceLabel[kPi0]="pi0";
292 fkSourceLabel[kElse]="others";
293 fkSourceLabel[kBeautyGamma]="beauty22gamma";
294 fkSourceLabel[kBeautyPi0]="beauty22pi0";
295 fkSourceLabel[kBeautyElse]="beauty22others";
298 TString hnopt="secvtx_";
299 for (Int_t isource = 0; isource < 10; isource++ ){
303 //qaList->AddLast(fSecVtxList);
306 //_______________________________________________________________________________________________
307 void AliHFEsecVtx::GetPrimaryCondition()
310 // get primary characteristics and set
314 AliKFVertex primVtxCopy(*(fESD1->GetPrimaryVertex()));
315 if( primVtxCopy.GetNDF() <1 ) return;
316 fPVx = primVtxCopy.GetX();
317 fPVy = primVtxCopy.GetY();
320 AliKFVertex primVtxCopy(*(fAOD1->GetPrimaryVertex()));
321 if( primVtxCopy.GetNDF() <1 ) return;
322 fPVx = primVtxCopy.GetX();
323 fPVy = primVtxCopy.GetY();
327 //_______________________________________________________________________________________________
328 void AliHFEsecVtx::PairAnalysis(AliVTrack* track1, AliVTrack* track2, Int_t index2)
331 // calculate e-h pair characteristics and tag pair
334 //later consider the below
335 Float_t dca1[2]={-999.,-999.}, dca2[2]={-999.,-999.};
336 Float_t cov1[3]={-999.,-999.,-999.}, cov2[3]={-999.,-999.,-999.};
338 Double_t dca1aod[2]={-999.,-999.}, dca2aod[2]={-999.,-999.};
339 Double_t cov1aod[3]={-999.,-999.,-999.}, cov2aod[3]={-999.,-999.,-999.};
341 if (IsAODanalysis()){
342 const AliAODVertex *primVtx = fAOD1->GetPrimaryVertex();
343 AliESDtrack esdTrk1(track1);
344 AliESDtrack esdTrk2(track2);
345 esdTrk1.PropagateToDCA(primVtx,0.,10000.,dca1aod,cov1aod);
346 esdTrk2.PropagateToDCA(primVtx,0.,10000.,dca2aod,cov2aod);
349 ((AliESDtrack*)track1)->GetImpactParameters(dca1,cov1);
350 ((AliESDtrack*)track2)->GetImpactParameters(dca2,cov2);
353 // apply pt dependent dca cut on hadrons
354 /*for(int ibin=0; ibin<6; ibin++){
355 if((track2->Pt()>fPtRng[ibin] && track2->Pt()<fPtRng[ibin+1]) && TMath::Abs(dca2[0])<fDcaCut[ibin]) return;
358 // get KF particle input pid
359 Int_t pdg1 = GetPDG(track1);
360 Int_t pdg2 = GetPDG(track2);
362 if(pdg1==-1 || pdg2==-1) {
363 //printf("out if considered pid range \n");
367 // create KF particle of pair
368 if(IsAODanalysis()) AliKFParticle::SetField(fAOD1->GetMagneticField());
369 else AliKFParticle::SetField(fESD1->GetMagneticField());
371 AliKFParticle kfTrack[2];
372 kfTrack[0] = AliKFParticle(*track1, pdg1);
373 kfTrack[1] = AliKFParticle(*track2, pdg2);
375 AliKFParticle kfSecondary(kfTrack[0],kfTrack[1]);
377 //secondary vertex point from kf particle
378 Double_t kfx = kfSecondary.GetX();
379 Double_t kfy = kfSecondary.GetY();
380 //Double_t kfz = kfSecondary.GetZ();
382 //momentum at the decay point from kf particle
383 Double_t kfpx = kfSecondary.GetPx();
384 Double_t kfpy = kfSecondary.GetPy();
385 //Double_t kfpz = kfSecondary.GetPz();
388 /* //directly use of ESD vertex
389 const AliESDVertex *pvertex = fESD1->GetPrimaryVertex();
391 pvertex->GetXYZ(xyzVtx);
393 Double_t dx = kfx-xyzVtx[0];
394 Double_t dy = kfy-xyzVtx[1];*/
396 AliKFVertex primVtxCopy(*(fESD1->GetPrimaryVertex()));
397 if( primVtxCopy.GetNDF() <1 ) return;
398 fPVx = primVtxCopy.GetX();
399 fPVy = primVtxCopy.GetY();
401 // printf("esdx= %lf kfx= %lf esdy= %lf kfy= %lf\n",xyzVtx[0],fPVx,xyzVtx[1],fPVy);
403 Double_t dx = kfx-fPVx;
404 Double_t dy = kfy-fPVy;
406 // discriminating variables
407 // invariant mass of the KF particle
408 Double_t invmass = -1;
409 Double_t invmassSigma = -1;
410 kfSecondary.GetMass(invmass,invmassSigma);
412 // chi2 of the KF particle
413 Double_t kfchi2 = -1;
414 if(kfSecondary.GetNDF()>0) kfchi2 = TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
416 // opening angle between two particles in XY plane
417 Double_t phi = kfTrack[0].GetAngleXY(kfTrack[1]);
418 Double_t cosphi = TMath::Cos(phi);
420 // DCA from primary to e-h KF particle (impact parameter of KF particle)
421 Double_t vtx[2]={fPVx, fPVy};
422 Double_t kfip = kfSecondary.GetDistanceFromVertexXY(vtx);
424 // projection of kf vertex vector to the kf momentum direction
425 Double_t signedLxy=-999.;
426 if((dx*kfpx+dy*kfpy)>0) signedLxy = TMath::Sqrt(dx*dx+dy*dy);
427 if((dx*kfpx+dy*kfpy)<0) signedLxy = -1*TMath::Sqrt(dx*dx+dy*dy);
428 //[the other way to think about]
429 //Double_t psqr = kfpx*kfpx+kfpy*kfpy;
430 //if(psqr>0) signedLxy=(dx*kfpx+dy*kfpy)/TMath::Sqrt(psqr);
432 //recalculating primary vertex after removing secvtx tracks --------------------------
434 trkid[0] = track1->GetID();
435 trkid[1] = track2->GetID();
437 RecalcPrimvtx(2, trkid, kfTrack);
438 Double_t dx2 = kfx-fPVx2;
439 Double_t dy2 = kfy-fPVy2;
441 // IP of sec particle recalculated based on recalculated primary vertex
442 Double_t vtx2[2]={fPVx2, fPVy2};
443 Double_t kfip2 = kfSecondary.GetDistanceFromVertexXY(vtx2);
444 // signed Lxy recalculated based on recalculated primary vertex
445 Double_t signedLxy2=-999.;
446 if((dx2*kfpx+dy2*kfpy)>0) signedLxy2 = TMath::Sqrt(dx2*dx2+dy2*dy2);
447 if((dx2*kfpx+dy2*kfpy)<0) signedLxy2 = -1*TMath::Sqrt(dx2*dx2+dy2*dy2);
448 //------------------------------------------------------------------------------------
452 if (HasMCData()) paircode = GetPairCode(track1,track2);
455 hfepair.SetTrkLabel(index2);
456 hfepair.SetInvmass(invmass);
457 hfepair.SetKFChi2(kfchi2);
458 hfepair.SetOpenangle(phi);
459 hfepair.SetCosOpenangle(cosphi);
460 hfepair.SetSignedLxy(signedLxy);
461 hfepair.SetSignedLxy2(signedLxy2);
462 hfepair.SetKFIP(kfip);
463 hfepair.SetKFIP2(kfip2);
464 hfepair.SetPairCode(paircode);
465 AddHFEpairToArray(&hfepair);
468 // fill into container for later QA
476 //if(cov1[0]>0) dataE[6]=Double_t(dca1[0]/cov1[0]);
477 //if(cov2[0]>0) dataE[7]=Double_t(dca2[0]/cov2[0]);
478 //dataE[6]=track1->Pt();
479 //dataE[7]=track2->Pt();
480 //dataE[6]=dca1[0]; //mjtmp
481 //dataE[7]=dca2[0]; //mjtmp
482 //dataE[8]=TMath::Abs(dca1[0]);
483 //dataE[9]=TMath::Abs(dca2[0]);
485 fPairQA->Fill(dataE);
489 //_______________________________________________________________________________________________
490 void AliHFEsecVtx::RunSECVTX(AliVTrack *track)
493 // run secondary vertexing algorithm and do tagging
496 //printf("number of considered pairs= %d\n",HFEpairs()->GetEntriesFast());
497 FindSECVTXCandid(track);
500 //_______________________________________________________________________________________________
501 void AliHFEsecVtx::FindSECVTXCandid(AliVTrack *track)
504 // find secondary vertex candidate and store them into container
507 AliVTrack *htrack[20];
508 //Int_t htracklabel[20];
509 //Int_t paircode[20];
510 //Double_t vtxchi2[20];
511 //Double_t dataE[7]={-999.,-999.,-999.,-999.,-1.,0,0};
513 fVtxchi2Tightcut=3.; // tight cut for pair
514 fVtxchi2Loosecut=5.; // loose cut for secvtx
516 if (HFEpairs()->GetEntriesFast()>20){
517 AliDebug(3, "number of paired hadron is over maximum(20)");
521 // get paired track objects
522 AliHFEpairs *pair=0x0;
523 if (IsAODanalysis()){
524 for (int ip=0; ip<HFEpairs()->GetEntriesFast(); ip++){
525 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ip));
526 //htracklabel[ip] = pair->GetTrkLabel();
527 htrack[ip] = fAOD1->GetTrack(pair->GetTrkLabel());
528 //if(pair->GetPairCode()==2 || pair->GetPairCode()==3) paircode[ip]=1;
529 //else paircode[ip]=0;
530 //vtxchi2[ip] = pair->GetKFChi2();
534 for (int ip=0; ip<HFEpairs()->GetEntriesFast(); ip++){
535 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ip));
536 //htracklabel[ip] = pair->GetTrkLabel();
537 htrack[ip] = fESD1->GetTrack(pair->GetTrkLabel());
538 //if(pair->GetPairCode()==2 || pair->GetPairCode()==3) paircode[ip]=1;
539 //else paircode[ip]=0;
540 //vtxchi2[ip] = pair->GetKFChi2();
544 Int_t nPairs = HFEpairs()->GetEntriesFast();
547 // 1 electron candidate + 1 track
549 if (pair->GetKFChi2() < fVtxchi2Tightcut) { // you can also put single track cut -> here you apply very tight cut for the pair
550 Fill2TrkSECVTX(track, pair);
554 //--------------------------------------------------------------
556 // 1 electron candidate + 2 tracks
558 CalcSECVTXProperty(track, htrack[0], htrack[1]); // calculate secondary vertex property
560 if (fKFchi2 < fVtxchi2Loosecut) { // -> here you apply rather loose cut
561 Fill3TrkSECVTX(track, 0, 1);
563 else{ // if doesn't pass the sec vtx chi2 cut
564 for(int jp=0; jp<2; jp++){
565 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jp));
566 if (pair->GetKFChi2() < fVtxchi2Tightcut){
567 Fill2TrkSECVTX(track, pair);
573 //--------------------------------------------------------------
575 // 1 electron candidate + 3 tracks
577 CalcSECVTXProperty(track, htrack[0], htrack[1], htrack[2]); // calculate secondary vertex property
579 if (fKFchi2 < fVtxchi2Loosecut) {
580 Fill4TrkSECVTX(track, 0, 1, 2);
584 for (int i=0; i<nPairs-1; i++){
585 for (int j=i+1; j<nPairs; j++){
586 CalcSECVTXProperty(track, htrack[i], htrack[j]);
587 if (fKFchi2 < fVtxchi2Loosecut) {
589 Fill3TrkSECVTX(track, i, j);
593 if(!fArethereSecVtx){
594 for(int jp=0; jp<nPairs; jp++){
595 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jp));
596 if (pair->GetKFChi2() < fVtxchi2Tightcut){
597 Fill2TrkSECVTX(track, pair);
604 //--------------------------------------------------------------
606 // 1 electron candidate + more than 3 tracks
609 for (int ih1=0; ih1<nPairs-2; ih1++){
610 for (int ih2=ih1+1; ih2<nPairs-1; ih2++){
611 for (int ih3=ih2+1; ih3<nPairs; ih3++){
612 CalcSECVTXProperty(track, htrack[ih1], htrack[ih2], htrack[ih3]); // calculate secondary vertex property
613 if (fKFchi2 < fVtxchi2Loosecut) {
615 Fill4TrkSECVTX(track, ih1, ih2, ih3);
620 if (!fArethereSecVtx){
622 for (int i=0; i<nPairs-1; i++){
623 for (int j=i+1; j<nPairs; j++){
624 CalcSECVTXProperty(track, htrack[i], htrack[j]);
625 if (fKFchi2 < fVtxchi2Loosecut) {
627 Fill3TrkSECVTX(track, i, j);
632 if (!fArethereSecVtx){
633 for(int jp=0; jp<nPairs; jp++){
634 pair = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jp));
635 if (pair->GetKFChi2() < fVtxchi2Tightcut){
636 Fill2TrkSECVTX(track, pair);
642 //--------------------------------------------------------------
646 //_______________________________________________________________________________________________
647 void AliHFEsecVtx::Fill4TrkSECVTX(AliVTrack* track, Int_t ipair, Int_t jpair, Int_t kpair)
650 // fill 3 tracks' secondary vertex properties
653 Double_t dataE[9]={-999.,-999.,-999.,-999.,-1.,0,0,-999.,-999.};
655 Int_t paircode1 = 0, paircode2 = 0, paircode3 = 0;
656 Int_t htracklabel1 = 0, htracklabel2= 0;
659 AliHFEpairs *pair1=0x0;
660 AliHFEpairs *pair2=0x0;
661 AliHFEpairs *pair3=0x0;
662 pair1 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ipair));
663 pair2 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jpair));
664 pair3 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(kpair));
666 htracklabel1 = pair1->GetTrkLabel();
667 htracklabel2 = pair2->GetTrkLabel();
669 if (pair1->GetPairCode()==2 || pair1->GetPairCode()==3) paircode1=1;
671 if (pair2->GetPairCode()==2 || pair2->GetPairCode()==3) paircode2=1;
673 if (pair3->GetPairCode()==2 || pair3->GetPairCode()==3) paircode3=1;
677 AliHFEsecVtxs hfesecvtx;
678 hfesecvtx.SetTrkLabel1(htracklabel1); // mj: not much meaningful for the moment
679 hfesecvtx.SetTrkLabel2(htracklabel2); // mj: not much meaningful for the moment
680 if(HasMCData()) hfesecvtx.SetMCCode(GetElectronSource(TMath::Abs(track->GetLabel())));
681 hfesecvtx.SetKFChi2(fKFchi2);
682 hfesecvtx.SetInvmass(fInvmass);
683 hfesecvtx.SetSignedLxy(fSignedLxy);
684 hfesecvtx.SetSignedLxy2(fSignedLxy2);
685 hfesecvtx.SetKFIP(fKFip);
686 hfesecvtx.SetKFIP2(fKFip2);
687 AddHFEsecvtxToArray(&hfesecvtx);
694 if(HasMCData()) dataE[4]=GetElectronSource(TMath::Abs(track->GetLabel()));
695 dataE[5]=4; //# of associated tracks
696 if(paircode1 & paircode2 & paircode3) dataE[6]=1;
697 else if(!paircode1 & !paircode2 & !paircode3) dataE[6]=0;
699 dataE[7]=fSignedLxy2;
700 dataE[8]=track->Pt();
701 fSecvtxQA->Fill(dataE);
704 //_______________________________________________________________________________________________
705 void AliHFEsecVtx::Fill3TrkSECVTX(AliVTrack* track, Int_t ipair, Int_t jpair)
708 // fill 3 tracks' secondary vertex properties
711 Double_t dataE[9]={-999.,-999.,-999.,-999.,-1.,0,0,-999.,-999.};
713 Int_t paircode1 = 0, paircode2 = 0;
714 Int_t htracklabel1 = 0, htracklabel2 = 0;
717 AliHFEpairs *pair1=0x0;
718 AliHFEpairs *pair2=0x0;
719 pair1 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(ipair));
720 pair2 = (AliHFEpairs*) (HFEpairs()->UncheckedAt(jpair));
722 htracklabel1 = pair1->GetTrkLabel();
723 htracklabel2 = pair2->GetTrkLabel();
725 if (pair1->GetPairCode()==2 || pair1->GetPairCode()==3) paircode1=1;
727 if (pair2->GetPairCode()==2 || pair2->GetPairCode()==3) paircode2=1;
731 // fill secondary vertex container
732 AliHFEsecVtxs hfesecvtx;
733 hfesecvtx.SetTrkLabel1(htracklabel1);
734 hfesecvtx.SetTrkLabel2(htracklabel2);
735 if(HasMCData()) hfesecvtx.SetMCCode(GetElectronSource(TMath::Abs(track->GetLabel())));
736 hfesecvtx.SetKFChi2(fKFchi2);
737 hfesecvtx.SetInvmass(fInvmass);
738 hfesecvtx.SetSignedLxy(fSignedLxy);
739 hfesecvtx.SetSignedLxy2(fSignedLxy2);
740 hfesecvtx.SetKFIP(fKFip);
741 hfesecvtx.SetKFIP2(fKFip2);
742 AddHFEsecvtxToArray(&hfesecvtx);
745 // fill debugging THnSparse
750 if(HasMCData()) dataE[4]=GetElectronSource(TMath::Abs(track->GetLabel()));
752 if(paircode1 & paircode2) dataE[6]=1;
753 else if(!paircode1 & !paircode2) dataE[6]=0;
755 dataE[7]=fSignedLxy2;
756 dataE[8]=track->Pt();
757 fSecvtxQA->Fill(dataE);
761 //_______________________________________________________________________________________________
762 void AliHFEsecVtx::Fill2TrkSECVTX(AliVTrack* track, AliHFEpairs *pair)
765 // fill 2 tracks' secondary vertex properties
768 Double_t dataE[9]={-999.,-999.,-999.,-999.,-1.,0,0,-999.,-999.};
771 if (pair->GetPairCode()==2 || pair->GetPairCode()==3) paircode=1;
774 // fill secondary vertex container
775 AliHFEsecVtxs hfesecvtx;
776 hfesecvtx.SetTrkLabel1(pair->GetTrkLabel());
777 hfesecvtx.SetTrkLabel2(-999);
778 if(HasMCData()) hfesecvtx.SetMCCode(GetElectronSource(TMath::Abs(track->GetLabel())));
779 hfesecvtx.SetInvmass(pair->GetInvmass());
780 hfesecvtx.SetKFChi2(pair->GetKFChi2());
781 hfesecvtx.SetSignedLxy(pair->GetSignedLxy());
782 hfesecvtx.SetSignedLxy2(pair->GetSignedLxy2());
783 hfesecvtx.SetKFIP(pair->GetKFIP());
784 hfesecvtx.SetKFIP2(pair->GetKFIP2());
785 AddHFEsecvtxToArray(&hfesecvtx);
788 // fill debugging THnSparse
789 dataE[0]=pair->GetInvmass();
790 dataE[1]=pair->GetKFChi2();
791 dataE[2]=pair->GetSignedLxy();
792 dataE[3]=pair->GetKFIP();
793 if (HasMCData()) dataE[4]=GetElectronSource(TMath::Abs(track->GetLabel()));
794 dataE[5]=2; //# of associated tracks
796 dataE[7]=pair->GetSignedLxy2();
797 dataE[8]=track->Pt();
798 fSecvtxQA->Fill(dataE);
802 //_______________________________________________________________________________________________
803 void AliHFEsecVtx::CalcSECVTXProperty(AliVTrack* track1, AliVTrack* track2, AliVTrack* track3)
806 // calculate secondary vertex properties
809 // get KF particle input pid
810 Int_t pdg1 = GetPDG(track1);
811 Int_t pdg2 = GetPDG(track2);
812 Int_t pdg3 = GetPDG(track3);
814 if(pdg1==-1 || pdg2==-1 || pdg3==-1) {
815 //printf("out if considered pid range \n");
819 // create KF particle of pair
820 if(IsAODanalysis()) AliKFParticle::SetField(fAOD1->GetMagneticField());
821 else AliKFParticle::SetField(fESD1->GetMagneticField());
822 AliKFParticle kfTrack[3];
823 kfTrack[0] = AliKFParticle(*track1, pdg1);
824 kfTrack[1] = AliKFParticle(*track2, pdg2);
825 kfTrack[2] = AliKFParticle(*track3, pdg3);
827 AliKFParticle kfSecondary(kfTrack[0],kfTrack[1],kfTrack[2]);
828 //AliKFParticle kfSecondary(kfTrack1,kfTrack2,kfTrack3);
830 //secondary vertex point from kf particle
831 Double_t kfx = kfSecondary.GetX();
832 Double_t kfy = kfSecondary.GetY();
833 //Double_t kfz = kfSecondary.GetZ();
835 //momentum at the decay point from kf particle
836 Double_t kfpx = kfSecondary.GetPx();
837 Double_t kfpy = kfSecondary.GetPy();
838 //Double_t kfpz = kfSecondary.GetPz();
840 Double_t dx = kfx-fPVx;
841 Double_t dy = kfy-fPVy;
843 // discriminating variables ----------------------------------------------------------
845 if(kfSecondary.GetNDF()>0) fKFchi2 = TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
847 // invariant mass of the KF particle
848 kfSecondary.GetMass(fInvmass,fInvmassSigma);
850 // DCA from primary to e-h KF particle (impact parameter of KF particle)
851 Double_t vtx[2]={fPVx, fPVy};
852 fKFip = kfSecondary.GetDistanceFromVertexXY(vtx);
854 if((dx*kfpx+dy*kfpy)>0) fSignedLxy= TMath::Sqrt(dx*dx+dy*dy);
855 if((dx*kfpx+dy*kfpy)<0) fSignedLxy= -1*TMath::Sqrt(dx*dx+dy*dy);
856 //[the other way to think about] - projection of kf vertex vector to the kf momentum direction
857 //Double_t psqr = kfpx*kfpx+kfpy*kfpy;
858 //if(psqr>0) fSignedLxy=(dx*kfpx+dy*kfpy)/TMath::Sqrt(psqr);
861 //recalculating primary vertex after removing secvtx tracks --------------------------
863 trkid[0] = track1->GetID();
864 trkid[1] = track2->GetID();
865 trkid[2] = track3->GetID();
867 RecalcPrimvtx(3, trkid, kfTrack);
868 Double_t dx2 = kfx-fPVx2;
869 Double_t dy2 = kfy-fPVy2;
871 // IP of sec particle recalculated based on recalculated primary vertex
872 Double_t vtx2[2]={fPVx2, fPVy2};
873 fKFip2 = kfSecondary.GetDistanceFromVertexXY(vtx2);
874 // signed Lxy recalculated based on recalculated primary vertex
875 if((dx2*kfpx+dy2*kfpy)>0) fSignedLxy2= TMath::Sqrt(dx2*dx2+dy2*dy2);
876 if((dx2*kfpx+dy2*kfpy)<0) fSignedLxy2= -1*TMath::Sqrt(dx2*dx2+dy2*dy2);
877 //------------------------------------------------------------------------------------
881 //_______________________________________________________________________________________________
882 void AliHFEsecVtx::CalcSECVTXProperty(AliVTrack* track1, AliVTrack* track2, AliVTrack* track3, AliVTrack* track4)
885 // calculate secondary vertex properties
888 // get KF particle input pid
889 Int_t pdg1 = GetPDG(track1);
890 Int_t pdg2 = GetPDG(track2);
891 Int_t pdg3 = GetPDG(track3);
892 Int_t pdg4 = GetPDG(track4);
894 if(pdg1==-1 || pdg2==-1 || pdg3==-1 || pdg4==-1) {
895 //printf("out if considered pid range \n");
899 // create KF particle of pair
900 if(IsAODanalysis()) AliKFParticle::SetField(fAOD1->GetMagneticField());
901 else AliKFParticle::SetField(fESD1->GetMagneticField());
903 AliKFParticle kfTrack[4];
904 kfTrack[0] = AliKFParticle(*track1, pdg1);
905 kfTrack[1] = AliKFParticle(*track2, pdg2);
906 kfTrack[2] = AliKFParticle(*track3, pdg3);
907 kfTrack[3] = AliKFParticle(*track4, pdg4);
909 AliKFParticle kfSecondary(kfTrack[0],kfTrack[1],kfTrack[2],kfTrack[3]);
911 //secondary vertex point from kf particle
912 Double_t kfx = kfSecondary.GetX();
913 Double_t kfy = kfSecondary.GetY();
914 //Double_t kfz = kfSecondary.GetZ();
916 //momentum at the decay point from kf particle
917 Double_t kfpx = kfSecondary.GetPx();
918 Double_t kfpy = kfSecondary.GetPy();
919 //Double_t kfpz = kfSecondary.GetPz();
921 Double_t dx = kfx-fPVx;
922 Double_t dy = kfy-fPVy;
924 // discriminating variables ----------------------------------------------------------
926 if(kfSecondary.GetNDF()>0) fKFchi2 = TMath::Sqrt(TMath::Abs(kfSecondary.GetChi2()/kfSecondary.GetNDF()));
928 // invariant mass of the KF particle
929 kfSecondary.GetMass(fInvmass,fInvmassSigma);
931 // DCA from primary to e-h KF particle (impact parameter of KF particle)
932 Double_t vtx[2]={fPVx, fPVy};
933 fKFip = kfSecondary.GetDistanceFromVertexXY(vtx);
935 if((dx*kfpx+dy*kfpy)>0) fSignedLxy= TMath::Sqrt(dx*dx+dy*dy);
936 if((dx*kfpx+dy*kfpy)<0) fSignedLxy= -1*TMath::Sqrt(dx*dx+dy*dy);
937 //[the other way to think about] - projection of kf vertex vector to the kf momentum direction
938 //Double_t psqr = kfpx*kfpx+kfpy*kfpy;
939 //if(psqr>0) fSignedLxy=(dx*kfpx+dy*kfpy)/TMath::Sqrt(psqr);
941 //recalculating primary vertex after removing secvtx tracks --------------------------
943 trkid[0] = track1->GetID();
944 trkid[1] = track2->GetID();
945 trkid[2] = track3->GetID();
946 trkid[3] = track4->GetID();
948 RecalcPrimvtx(4, trkid, kfTrack);
949 Double_t dx2 = kfx-fPVx2;
950 Double_t dy2 = kfy-fPVy2;
952 // IP of sec particle recalculated based on recalculated primary vertex
953 Double_t vtx2[2]={fPVx2, fPVy2};
954 fKFip2 = kfSecondary.GetDistanceFromVertexXY(vtx2);
955 // signed Lxy recalculated based on recalculated primary vertex
956 if((dx2*kfpx+dy2*kfpy)>0) fSignedLxy2= TMath::Sqrt(dx2*dx2+dy2*dy2);
957 if((dx2*kfpx+dy2*kfpy)<0) fSignedLxy2= -1*TMath::Sqrt(dx2*dx2+dy2*dy2);
958 //------------------------------------------------------------------------------------
962 //_______________________________________________________________________________________________
963 void AliHFEsecVtx::RecalcPrimvtx(Int_t nkftrk, const Int_t * const trkid, const AliKFParticle * const kftrk){
965 // reccalculate primary vertex after removing considering track in the calculation
968 const AliESDVertex *primvtx = fESD1->GetPrimaryVertex();
970 AliKFVertex kfESDprimary;
971 Int_t n = primvtx->GetNIndices();
976 if (n>0 && primvtx->GetStatus()){
977 kfESDprimary = AliKFVertex(*primvtx);
978 UShort_t *priIndex = primvtx->GetIndices();
979 for(Int_t j=0; j<nkftrk; j++){
980 for (Int_t i=0;i<n;i++){
981 Int_t idx = Int_t(priIndex[i]);
982 if (idx == trkid[j]){
983 kfESDprimary -= kftrk[j];
990 fPVx2 = kfESDprimary.GetX();
991 fPVy2 = kfESDprimary.GetY();
995 //_______________________________________________________________________________________________
996 Int_t AliHFEsecVtx::GetMCPID(const AliESDtrack *track)
1002 AliMCParticle *mctrack = NULL;
1003 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(track->GetLabel()))))) return 0;
1004 TParticle *mcpart = mctrack->Particle();
1006 if ( !mcpart ) return 0;
1007 Int_t pdgCode = mcpart->GetPdgCode();
1012 //_______________________________________________________________________________________________
1013 Int_t AliHFEsecVtx::GetPairOriginESD(AliESDtrack* trk1, AliESDtrack* trk2)
1016 // return pdg code of the origin(source) of the pair
1019 // ---*---*---*-----ancester A----- track1
1022 // => if they originated from same ancester,
1023 // then return "the absolute value of pdg code of ancester A"
1025 // ---*---*---B hadron-----ancester A----- track1
1028 // => if they originated from same ancester, and this ancester originally comes from B hadrons
1029 // then return -1*"the absolute value of pdg code of ancester A"
1031 // caution : it can also return parton pdg code if it originated from same string or gluon spliting.
1034 if (trk1->GetLabel()<0 || trk2->GetLabel()<0) return 0;
1036 AliMCParticle *mctrack = NULL;
1037 AliMCParticle *mctrack1 = NULL;
1038 AliMCParticle *mctrack2 = NULL;
1039 if(!(mctrack1 = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(trk1->GetLabel()))))) return 0;
1040 if(!(mctrack2 = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(trk2->GetLabel()))))) return 0;
1041 TParticle *part1 = mctrack1->Particle();
1042 TParticle *part2 = mctrack2->Particle();
1044 TParticle* part2cp = part2;
1045 if (!(part1) || !(part2)) return 0;
1049 //if the two tracks' mother's label is same, get the mother info
1050 //in case of charm, check if it originated from beauty
1051 for (Int_t i=0; i<10; i++){ //check up to 10 ancesters
1052 Int_t label1 = part1->GetFirstMother();
1053 if (label1 < 0) return 0;
1055 for (Int_t j=0; j<10; j++){ //check up to 10 ancesters
1056 Int_t label2 = part2->GetFirstMother();
1057 if (label2 < 0) break;
1059 if (label1 == label2){ //check if two tracks are originated from same mother
1060 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(label2))))) return 0;
1061 TParticle* commonmom = mctrack->Particle();
1063 srcpdg = abs(commonmom->GetPdgCode());
1065 //check ancester to see if it is originally from beauty
1066 for (Int_t k=0; k<10; k++){ //check up to 10 ancesters
1067 Int_t ancesterlabel = commonmom->GetFirstMother();
1068 if (ancesterlabel < 0) return srcpdg; // if there is no more commonancester, return commonmom's pdg
1070 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(ancesterlabel))))) return 0;
1071 TParticle* commonancester = mctrack->Particle();
1073 Int_t ancesterpdg = abs(commonancester->GetPdgCode());
1075 for (Int_t l=0; l<fNparents; l++){
1076 if (abs(ancesterpdg)==fParentSelect[1][l]){
1077 srcpdg = -1*srcpdg; //multiply -1 for hadron from bottom
1081 commonmom = commonancester;
1084 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(label2))))) return 0;
1085 part2 = mctrack->Particle(); //if their mother is different, go to earlier generation of 2nd particle
1087 if (!(part2)) break;
1089 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(label1))))) return 0;
1090 part1 = mctrack->Particle(); //if their mother is different, go to earlier generation of 1st particle
1092 if (!(part1)) return 0;
1098 //_______________________________________________________________________________________________
1099 Int_t AliHFEsecVtx::GetPairOriginAOD(AliAODTrack* trk1, AliAODTrack* trk2)
1103 // return pdg code of the origin(source) of the pair
1106 // ---*---*---*-----ancester A----- track1
1109 // => if they originated from same ancester,
1110 // then return "the absolute value of pdg code of ancester A"
1112 // ---*---*---B hadron-----ancester A----- track1
1115 // => if they originated from same ancester, and this ancester originally comes from B hadrons
1116 // then return -1*"the absolute value of pdg code of ancester A"
1118 // caution : it can also return parton pdg code if it originated from same string or gluon spliting.
1121 if (trk1->GetLabel()<0 || trk2->GetLabel()<0) return 0;
1122 AliAODMCParticle *part1 = (AliAODMCParticle*)fMCArray->At(trk1->GetLabel());
1123 AliAODMCParticle *part2 = (AliAODMCParticle*)fMCArray->At(trk2->GetLabel());
1124 AliAODMCParticle *part2cp = part2;
1125 if (!(part1) || !(part2)) return 0;
1129 //if the two tracks' mother's label is same, get the mother info
1130 //in case of charm, check if it originated from beauty
1131 for (Int_t i=0; i<10; i++){ //check up to 10 ancesters
1132 Int_t label1 = part1->GetMother();
1133 if (label1 < 0) return 0;
1135 for (Int_t j=0; j<10; j++){ //check up to 10 ancesters
1136 Int_t label2 = part2->GetMother();
1137 if (label2 < 0) return 0;
1139 if (label1 == label2){ //check if two tracks are originated from same mother
1140 AliAODMCParticle *commonmom = (AliAODMCParticle*)fMCArray->At(label1);
1141 srcpdg = abs(commonmom->GetPdgCode());
1143 //check ancester to see if it is originally from beauty
1144 for (Int_t k=0; k<10; k++){ //check up to 10 ancesters
1145 Int_t ancesterlabel = commonmom->GetMother();
1146 if (ancesterlabel < 0) return srcpdg; // if there is no more commonancester, return commonmom's pdg
1148 AliAODMCParticle *commonancester = (AliAODMCParticle*)fMCArray->At(ancesterlabel);
1149 Int_t ancesterpdg = abs(commonancester->GetPdgCode());
1151 for (Int_t l=0; l<fNparents; l++){
1152 if (abs(ancesterpdg)==fParentSelect[1][l]){
1153 srcpdg = -1*srcpdg; //multiply -1 for charm from bottom
1157 commonmom = commonancester;
1160 part2 = (AliAODMCParticle*)fMCArray->At(label2); //if their mother is different, go to earlier generation of 2nd particle
1161 if (!(part2)) break;
1163 part1 = (AliAODMCParticle*)fMCArray->At(label1); //if their mother is different, go to earlier generation of 2nd particle
1165 if (!(part1)) return 0;
1171 //_______________________________________________________________________________________________
1172 Int_t AliHFEsecVtx::GetPairCode(const AliVTrack* const trk1, const AliVTrack* const trk2)
1175 // return pair code which is predefinded as:
1176 // kDirectCharm, kDirectBeauty, kBeautyCharm, kGamma, kPi0,
1177 // kElse, kBeautyGamma, kBeautyPi0, kBeautyElse
1181 Int_t srccode = kElse;
1183 if(IsAODanalysis()) srcpdg = GetPairOriginAOD((AliAODTrack*)trk1,(AliAODTrack*)trk2);
1184 else srcpdg = GetPairOriginESD((AliESDtrack*)trk1,(AliESDtrack*)trk2);
1186 if (srcpdg < 0) srccode = kBeautyElse;
1187 for (Int_t i=0; i<fNparents; i++){
1188 if (abs(srcpdg)==fParentSelect[0][i]) {
1189 if (srcpdg>0) srccode = kDirectCharm;
1190 if (srcpdg<0) srccode = kBeautyCharm;
1192 if (abs(srcpdg)==fParentSelect[1][i]) {
1193 if (srcpdg>0) srccode = kDirectBeauty;
1194 if (srcpdg<0) return kElse;
1197 if (srcpdg == 22) srccode = kGamma;
1198 if (srcpdg == -22) srccode = kBeautyGamma;
1199 if (srcpdg == 111) srccode = kPi0;
1200 if (srcpdg == -111) srccode = kBeautyPi0;
1205 //_______________________________________________________________________________________________
1206 Int_t AliHFEsecVtx::GetElectronSource(Int_t iTrack)
1209 // return decay electron's origin
1213 AliDebug(1, "Stack label is negative, return\n");
1217 AliMCParticle *mctrack = NULL;
1218 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(iTrack))))) return -1;
1219 TParticle *mcpart = mctrack->Particle();
1222 AliDebug(1, "no mc particle, return\n");
1226 if ( abs(mcpart->GetPdgCode()) != 11 ) return kMisID;
1228 // if ( abs(mcpart->GetPdgCode()) != 11 ) return -1; // check if it is electron !
1230 Int_t iLabel = mcpart->GetFirstMother();
1232 AliDebug(1, "Stack label is negative, return\n");
1237 Bool_t isFinalOpenCharm = kFALSE;
1239 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(iLabel))))) return -1;
1240 TParticle *partMother = mctrack->Particle();
1242 Int_t maPdgcode = partMother->GetPdgCode();
1244 // if the mother is charmed hadron
1245 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
1247 for (Int_t i=0; i<fNparents; i++){
1248 if (abs(maPdgcode)==fParentSelect[0][i]){
1249 isFinalOpenCharm = kTRUE;
1252 if (!isFinalOpenCharm) return -1;
1254 // iterate until you find B hadron as a mother or become top ancester
1255 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1257 Int_t jLabel = partMother->GetFirstMother();
1259 origin = kDirectCharm;
1262 if (jLabel < 0){ // safety protection
1263 AliDebug(1, "Stack label is negative, return\n");
1267 // if there is an ancester
1268 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1269 TParticle *grandMa = mctrack->Particle();
1271 Int_t grandMaPDG = grandMa->GetPdgCode();
1273 for (Int_t j=0; j<fNparents; j++){
1274 if (abs(grandMaPDG)==fParentSelect[1][j]){
1275 origin = kBeautyCharm;
1280 partMother = grandMa;
1281 } // end of iteration
1283 else if ( int(abs(maPdgcode)/100.) == kBeauty || int(abs(maPdgcode)/1000.) == kBeauty ) {
1284 for (Int_t i=0; i<fNparents; i++){
1285 if (abs(maPdgcode)==fParentSelect[1][i]){
1286 origin = kDirectBeauty;
1292 //============ gamma ================
1293 else if ( abs(maPdgcode) == 22 ) {
1296 // iterate until you find B hadron as a mother or become top ancester
1297 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1299 Int_t jLabel = partMother->GetFirstMother();
1304 if (jLabel < 0){ // safety protection
1305 AliDebug(1, "Stack label is negative, return\n");
1309 // if there is an ancester
1310 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1311 TParticle *grandMa = mctrack->Particle();
1313 Int_t grandMaPDG = grandMa->GetPdgCode();
1315 for (Int_t j=0; j<fNparents; j++){
1316 if (abs(grandMaPDG)==fParentSelect[1][j]){
1317 origin = kBeautyGamma;
1322 partMother = grandMa;
1323 } // end of iteration
1328 //============ pi0 ================
1329 else if ( abs(maPdgcode) == 111 ) {
1332 // iterate until you find B hadron as a mother or become top ancester
1333 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1335 Int_t jLabel = partMother->GetFirstMother();
1340 if (jLabel < 0){ // safety protection
1341 AliDebug(1, "Stack label is negative, return\n");
1345 // if there is an ancester
1346 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1347 TParticle *grandMa = mctrack->Particle();
1349 Int_t grandMaPDG = grandMa->GetPdgCode();
1351 for (Int_t j=0; j<fNparents; j++){
1352 if (abs(grandMaPDG)==fParentSelect[1][j]){
1353 origin = kBeautyPi0;
1358 partMother = grandMa;
1359 } // end of iteration
1366 // iterate until you find B hadron as a mother or become top ancester
1367 for (Int_t i=1; i<100; i++){ // check back to the 100 generation older
1369 Int_t jLabel = partMother->GetFirstMother();
1374 if (jLabel < 0){ // safety protection
1375 AliDebug(1, "Stack label is negative, return\n");
1379 // if there is an ancester
1380 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1381 TParticle *grandMa = mctrack->Particle();
1383 Int_t grandMaPDG = grandMa->GetPdgCode();
1385 for (Int_t j=0; j<fNparents; j++){
1386 if (abs(grandMaPDG)==fParentSelect[1][j]){
1387 origin = kBeautyElse;
1392 partMother = grandMa;
1393 } // end of iteration
1399 //_______________________________________________________________________________________________
1400 Int_t AliHFEsecVtx::GetPDG(AliVTrack *track)
1403 // get KF particle input pdg for mass hypothesis
1408 if (fUseMCPID && HasMCData()){
1409 pdgCode = GetMCPDG(track);
1414 GetESDPID((AliESDtrack*)track, pid, prob);
1416 case 0: pdgCode = 11; break;
1417 case 1: pdgCode = 13; break;
1418 case 2: pdgCode = 211; break;
1419 case 3: pdgCode = 321; break;
1420 case 4: pdgCode = 2212; break;
1421 default: pdgCode = -1;
1425 Int_t pid = ((AliAODTrack*)track)->GetMostProbablePID();
1427 case 0: pdgCode = 11; break;
1428 case 1: pdgCode = 13; break;
1429 case 2: pdgCode = 211; break;
1430 case 3: pdgCode = 321; break;
1431 case 4: pdgCode = 2212; break;
1432 default: pdgCode = -1;
1439 //_______________________________________________________________________________________________
1440 Int_t AliHFEsecVtx::GetMCPDG(const AliVTrack *track)
1443 // return mc pdg code
1446 Int_t label = TMath::Abs(track->GetLabel());
1448 AliMCParticle *mctrack = NULL;
1450 if (IsAODanalysis()) {
1451 AliAODMCParticle *mcpart = (AliAODMCParticle*)fMCArray->At(label);
1452 if ( !mcpart ) return 0;
1453 pdgCode = mcpart->GetPdgCode();
1456 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(label))))) return 0;
1457 TParticle *mcpart = mctrack->Particle();
1459 if ( !mcpart ) return 0;
1460 pdgCode = mcpart->GetPdgCode();
1466 //______________________________________________________________________________
1467 void AliHFEsecVtx::GetESDPID(AliESDtrack *track, Int_t &recpid, Double_t &recprob)
1470 // calculate likehood for esd pid
1479 Double_t probability[5];
1481 // get probability of the diffenrent particle types
1482 track->GetESDpid(probability);
1484 // find most probable particle in ESD pid
1485 // 0:Electron - 1:Muon - 2:Pion - 3:Kaon - 4:Proton
1486 ipid = TMath::LocMax(5,probability);
1487 max = TMath::MaxElement(5,probability);
1493 //_____________________________________________________________________________
1494 void AliHFEsecVtx::AddHFEpairToArray(const AliHFEpairs* const pair)
1497 // Add a HFE pair to the array
1500 Int_t n = HFEpairs()->GetEntriesFast();
1501 if(n!=fNoOfHFEpairs)AliError(Form("fNoOfHFEpairs != HFEpairs()->GetEntriesFast %i != %i \n", fNoOfHFEpairs, n));
1502 new((*HFEpairs())[n]) AliHFEpairs(*pair);
1505 //_____________________________________________________________________________
1506 TClonesArray *AliHFEsecVtx::HFEpairs()
1509 // Returns the list of HFE pairs
1513 fHFEpairs = new TClonesArray("AliHFEpairs", 200);
1518 //_____________________________________________________________________________
1519 void AliHFEsecVtx::DeleteHFEpairs()
1522 // Delete the list of HFE pairs
1526 fHFEpairs->Delete();
1531 //_____________________________________________________________________________
1532 void AliHFEsecVtx::InitHFEpairs()
1535 // Initialization should be done before make all possible pairs for a given electron candidate
1541 //_____________________________________________________________________________
1542 void AliHFEsecVtx::AddHFEsecvtxToArray(const AliHFEsecVtxs* const secvtx)
1545 // Add a HFE secondary vertex to the array
1548 Int_t n = HFEsecvtxs()->GetEntriesFast();
1549 if(n!=fNoOfHFEsecvtxs)AliError(Form("fNoOfHFEsecvtxs != HFEsecvtxs()->GetEntriesFast %i != %i \n", fNoOfHFEsecvtxs, n));
1550 new((*HFEsecvtxs())[n]) AliHFEsecVtxs(*secvtx);
1553 //_____________________________________________________________________________
1554 TClonesArray *AliHFEsecVtx::HFEsecvtxs()
1557 // Returns the list of HFE secvtx
1561 fHFEsecvtxs = new TClonesArray("AliHFEsecVtxs", 200);
1566 //_____________________________________________________________________________
1567 void AliHFEsecVtx::DeleteHFEsecvtxs()
1570 // Delete the list of HFE pairs
1574 fHFEsecvtxs->Delete();
1575 //delete fHFEsecvtx;
1579 //_____________________________________________________________________________
1580 void AliHFEsecVtx::InitHFEsecvtxs()
1583 // Initialization should be done
1586 fNoOfHFEsecvtxs = 0;
1589 //____________________________________________________________
1590 void AliHFEsecVtx::MakeContainer(){
1596 const Int_t nDimPair=6;
1597 Int_t nBinPair[nDimPair] = {200, 500, 314, 2000, 2000, 13};
1598 //Int_t nBinPair[nDimPair] = {200, 500, 314, 2000, 2000, 13, 60, 60, 2000, 2000};
1599 const Double_t kInvmassmin = 0., kInvmassmax = 20.;
1600 const Double_t kKFChi2min = 0, kKFChi2max= 50;
1601 const Double_t kOpenanglemin = 0, kOpenanglemax = 3.14;
1602 const Double_t kSignedLxymin = -10, kSignedLxymax= 10;
1603 const Double_t kKFIPmin = -10, kKFIPmax= 10;
1604 const Double_t kPairCodemin = -1, kPairCodemax= 12;
1605 //const Double_t kPtmin = 0, kPtmax= 30;
1606 //const Double_t kDCAsigmin = -5, kDCAsigmax= 5;
1608 Double_t* binEdgesPair[nDimPair];
1609 for(Int_t ivar = 0; ivar < nDimPair; ivar++)
1610 binEdgesPair[ivar] = new Double_t[nBinPair[ivar] + 1];
1612 for(Int_t i=0; i<=nBinPair[0]; i++) binEdgesPair[0][i]=(Double_t)kInvmassmin + (kInvmassmax - kInvmassmin)/nBinPair[0]*(Double_t)i;
1613 for(Int_t i=0; i<=nBinPair[1]; i++) binEdgesPair[1][i]=(Double_t)kKFChi2min + (kKFChi2max - kKFChi2min)/nBinPair[1]*(Double_t)i;
1614 for(Int_t i=0; i<=nBinPair[2]; i++) binEdgesPair[2][i]=(Double_t)kOpenanglemin + (kOpenanglemax - kOpenanglemin)/nBinPair[2]*(Double_t)i;
1615 for(Int_t i=0; i<=nBinPair[3]; i++) binEdgesPair[3][i]=(Double_t)kSignedLxymin + (kSignedLxymax - kSignedLxymin)/nBinPair[3]*(Double_t)i;
1616 for(Int_t i=0; i<=nBinPair[4]; i++) binEdgesPair[4][i]=(Double_t)kKFIPmin + (kKFIPmax - kKFIPmin)/nBinPair[4]*(Double_t)i;
1617 for(Int_t i=0; i<=nBinPair[5]; i++) binEdgesPair[5][i]=(Double_t)kPairCodemin + (kPairCodemax - kPairCodemin)/nBinPair[5]*(Double_t)i;
1618 //for(Int_t i=0; i<=nBinPair[6]; i++) binEdgesPair[6][i]=(Double_t)kPtmin + (kPtmax - kPtmin)/nBinPair[6]*(Double_t)i;
1619 //for(Int_t i=0; i<=nBinPair[7]; i++) binEdgesPair[7][i]=binEdgesPair[6][i];
1620 //for(Int_t i=0; i<=nBinPair[6]; i++) binEdgesPair[6][i]=(Double_t)kDCAsigmin + (kDCAsigmax - kDCAsigmin)/nBinPair[6]*(Double_t)i;
1621 //for(Int_t i=0; i<=nBinPair[7]; i++) binEdgesPair[7][i]=binEdgesPair[6][i];
1623 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);
1624 //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);
1625 for(Int_t idim = 0; idim < nDimPair; idim++){
1626 fPairQA->SetBinEdges(idim, binEdgesPair[idim]);
1629 fSecVtxList->AddAt(fPairQA,0);
1631 const Int_t nDimSecvtx=9;
1632 Double_t* binEdgesSecvtx[nDimSecvtx];
1633 Int_t nBinSecvtx[nDimSecvtx] = {200, 500, 2000, 2000, 13, 10, 4, 2000, 500};
1634 const Double_t kNtrksmin = 0, kNtrksmax= 10;
1635 const Double_t kTrueBmin = 0, kTrueBmax= 4;
1636 const Double_t kPtmin = 0, kPtmax= 50;
1637 for(Int_t ivar = 0; ivar < nDimSecvtx; ivar++)
1638 binEdgesSecvtx[ivar] = new Double_t[nBinSecvtx[ivar] + 1];
1640 for(Int_t i=0; i<=nBinSecvtx[0]; i++) binEdgesSecvtx[0][i]=binEdgesPair[0][i];
1641 for(Int_t i=0; i<=nBinSecvtx[1]; i++) binEdgesSecvtx[1][i]=binEdgesPair[1][i];
1642 for(Int_t i=0; i<=nBinSecvtx[2]; i++) binEdgesSecvtx[2][i]=binEdgesPair[3][i];
1643 for(Int_t i=0; i<=nBinSecvtx[3]; i++) binEdgesSecvtx[3][i]=binEdgesPair[4][i];
1644 for(Int_t i=0; i<=nBinSecvtx[4]; i++) binEdgesSecvtx[4][i]=binEdgesPair[5][i];
1645 for(Int_t i=0; i<=nBinSecvtx[5]; i++) binEdgesSecvtx[5][i]=(Double_t)kNtrksmin + (kNtrksmax - kNtrksmin)/nBinSecvtx[5]*(Double_t)i;
1646 for(Int_t i=0; i<=nBinSecvtx[6]; i++) binEdgesSecvtx[6][i]=(Double_t)kTrueBmin + (kTrueBmax - kTrueBmin)/nBinSecvtx[6]*(Double_t)i;
1647 for(Int_t i=0; i<=nBinSecvtx[7]; i++) binEdgesSecvtx[7][i]=binEdgesPair[3][i];
1648 for(Int_t i=0; i<=nBinSecvtx[8]; i++) binEdgesSecvtx[8][i]=(Double_t)kPtmin + (kPtmax - kPtmin)/nBinSecvtx[8]*(Double_t)i;
1650 fSecvtxQA = new THnSparseF("secvtxQA", "QA for Secvtx; invmass[GeV/c^2]; KF chi2; signed Lxy; KF ip; pair code; n tracks ", nDimSecvtx, nBinSecvtx);
1651 for(Int_t idim = 0; idim < nDimSecvtx; idim++){
1652 fSecvtxQA->SetBinEdges(idim, binEdgesSecvtx[idim]);
1655 fSecVtxList->AddAt(fSecvtxQA,1);
1657 for(Int_t ivar = 0; ivar < nDimPair; ivar++)
1658 delete binEdgesPair[ivar];
1659 for(Int_t ivar = 0; ivar < nDimSecvtx; ivar++)
1660 delete binEdgesSecvtx[ivar];
1663 //____________________________________________________________
1664 void AliHFEsecVtx::MakeHistos(Int_t step){
1670 TString hname=Form("step%d",step);
1673 const Double_t kPtbound[2] = {0.1, 20.};
1675 iBin[0] = 44; // bins in pt
1676 Double_t* binEdges[1];
1677 binEdges[0] = AliHFEtools::MakeLogarithmicBinning(iBin[0], kPtbound[0], kPtbound[1]);
1679 fSecVtxList->AddAt(new TH1F(hname+"taggedElec", "pT of e", iBin[0],binEdges[0]), step);
1680 fSecVtxList->AddAt(new TH1F(hname+"charmElec", "pT of e", iBin[0],binEdges[0]), step+1);
1681 fSecVtxList->AddAt(new TH1F(hname+"beautyElec", "pT of e", iBin[0],binEdges[0]), step+2);
1682 fSecVtxList->AddAt(new TH1F(hname+"conversionElec", "pT of e", iBin[0],binEdges[0]), step+3);
1683 fSecVtxList->AddAt(new TH1F(hname+"ebgElec", "pT of e", iBin[0],binEdges[0]), step+4);
1684 fSecVtxList->AddAt(new TH1F(hname+"hcontaminElec", "pT of e", iBin[0],binEdges[0]), step+5);
1685 fSecVtxList->AddAt(new TH1F(hname+"elseElec", "pT of e", iBin[0],binEdges[0]), step+6);
1688 //____________________________________________________________
1689 void AliHFEsecVtx::FillHistos(Int_t step, const AliESDtrack *track){
1697 AliMCParticle *mctrack = NULL;
1698 TParticle* mcpart = NULL;
1700 (static_cast<TH1F *>(fSecVtxList->At(step)))->Fill(track->Pt()); // electrons tagged
1702 if(HasMCData() && fMCQA){
1703 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(track->GetLabel()))))) return;
1704 mcpart = mctrack->Particle();
1706 Int_t esource=fMCQA->GetElecSource(mcpart);
1708 //if(!(dynamic_cast<TH1F *>(fSecVtxList->At(step+1)))) return;
1709 (static_cast<TH1F *>(fSecVtxList->At(step+1)))->Fill(mcpart->Pt()); //charm
1711 else if(esource==2 || esource==3) {
1712 //if(!(dynamic_cast<TH1F *>(fSecVtxList->At(step+2)))) return;
1713 (static_cast<TH1F *>(fSecVtxList->At(step+2)))->Fill(mcpart->Pt()); //beauty
1715 else if(esource==4) {
1716 //if(!(dynamic_cast<TH1F *>(fSecVtxList->At(step+3)))) return;
1717 (static_cast<TH1F *>(fSecVtxList->At(step+3)))->Fill(mcpart->Pt()); //conversion
1719 else if(esource==7) {
1720 //if(!(dynamic_cast<TH1F *>(fSecVtxList->At(step+5)))) return;
1721 (static_cast<TH1F *>(fSecVtxList->At(step+5)))->Fill(mcpart->Pt()); //contamination
1723 else if(!(esource<0)) {
1724 //if(!(dynamic_cast<TH1F *>(fSecVtxList->At(step+4)))) return;
1725 (static_cast<TH1F *>(fSecVtxList->At(step+4)))->Fill(mcpart->Pt()); //e backgrounds
1728 //if(!(dynamic_cast<TH1F *>(fSecVtxList->At(step+6)))) return;
1729 (static_cast<TH1F *>(fSecVtxList->At(step+6)))->Fill(mcpart->Pt()); //something else?