AliPhysics  bba8f44 (bba8f44)
AliAnalysisTaskDmesonJets.cxx
Go to the documentation of this file.
1 /*************************************************************************
2 * Copyright(c) 1998-2016, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15 
16 //C++
17 #include <sstream>
18 
19 // Root
20 #include <TClonesArray.h>
21 #include <TDatabasePDG.h>
22 #include <TParticlePDG.h>
23 #include <TVector3.h>
24 #include <THnSparse.h>
25 #include <TParticle.h>
26 #include <TMath.h>
27 #include <THashList.h>
28 #include <TFile.h>
29 #include <TRandom3.h>
30 
31 // Aliroot general
32 #include "AliLog.h"
33 #include "AliEMCALGeometry.h"
34 #include "AliAnalysisManager.h"
35 #include "AliVEventHandler.h"
36 
37 // Aliroot HF
38 #include "AliAODRecoCascadeHF.h"
40 #include "AliRDHFCutsD0toKpi.h"
43 #include "AliHFTrackContainer.h"
44 #include "AliAnalysisVertexingHF.h"
45 
46 // Aliroot EMCal jet framework
47 #include "AliEmcalJetTask.h"
48 #include "AliEmcalJet.h"
49 #include "AliJetContainer.h"
50 #include "AliParticleContainer.h"
51 #include "AliEmcalParticle.h"
52 #include "AliFJWrapper.h"
53 #include "AliRhoParameter.h"
54 
56 
57 AliAnalysisTaskDmesonJets::AliEventNotFound::AliEventNotFound(const std::string& class_name, const std::string& method_name) :
58  std::exception(),
59  fClassName(class_name),
60  fAccessMethodName(method_name)
61 {
62  std::stringstream what_str;
63  what_str << "ALICE event not found in class '" << fClassName << "' using method '" << method_name << "'.";
64  fWhat = what_str.str();
65 }
66 
67 #if !(defined(__CINT__) || defined(__MAKECINT__))
69 {
70  return fWhat.c_str();
71 }
72 #endif
73 
74 // Definitions of class AliAnalysisTaskDmesonJets::AliJetInfo
75 
79 
87 {
88  dphi = TVector2::Phi_mpi_pi(fMomentum.Phi() - jet.Phi());;
89  deta = fMomentum.Eta() - jet.Eta();
90  return TMath::Sqrt(dphi*dphi + deta*deta);
91 }
92 
98 {
99  Double_t deta = 0;
100  Double_t dphi = 0;
101  return GetDistance(jet, deta, dphi);
102 }
103 
104 // Definitions of class AliAnalysisTaskDmesonJets::AliDmesonJetInfo
105 
109 
112  fDmesonParticle(0),
113  fD(),
114  fSoftPionPt(0),
115  fInvMass2Prong(0),
116  fJets(),
117  fMCLabel(-1),
118  fReconstructed(kFALSE),
119  fParton(0),
120  fPartonType(0),
121  fAncestor(0),
122  fD0D0bar(kFALSE),
123  fSelectionType(0),
124  fEvent(nullptr)
125 {
126 }
127 
133  fD(source.fD),
134  fSoftPionPt(source.fSoftPionPt),
136  fJets(source.fJets),
137  fMCLabel(source.fMCLabel),
139  fParton(source.fParton),
140  fPartonType(source.fPartonType),
141  fAncestor(source.fAncestor),
142  fD0D0bar(source.fD0D0bar),
144  fEvent(source.fEvent)
145 {
146 }
147 
152 {
153  new (this) AliDmesonJetInfo(source);
154  return *this;
155 }
156 
159 {
160  fD.SetPtEtaPhiE(0,0,0,0);
161  fSoftPionPt = 0;
162  fInvMass2Prong = 0;
163  fDmesonParticle = 0;
164  fMCLabel = -1;
165  fReconstructed = kFALSE;
166  fParton = 0;
167  fPartonType = 0;
168  fAncestor = 0;
169  fD0D0bar = kFALSE;
170  for (auto &jet : fJets) {
171  jet.second.fMomentum.SetPtEtaPhiE(0,0,0,0);
172  jet.second.fNConstituents = 0;
173  jet.second.fNEF = 0;
174  jet.second.fMaxChargedPt = 0;
175  jet.second.fMaxNeutralPt = 0;
176  }
177 }
178 
181 {
182  Printf("Printing D Meson Jet object.");
183  Printf("D Meson: pT = %.3f, eta = %.3f, phi = %.3f, inv. mass = %.3f", fD.Pt(), fD.Eta(), fD.Phi_0_2pi(), fD.M());
184  Printf("Soft pion pT: %.3f. 2-Prong Invariant mass = %.3f", fSoftPionPt, fInvMass2Prong);
185  for (auto &jet : fJets) {
186  Printf("Jet %s: pT = %.3f, eta = %.3f, phi = %.3f", jet.first.c_str(), jet.second.Pt(), jet.second.Eta(), jet.second.Phi_0_2pi());
187  Printf("Jet N Consituents = %d", jet.second.fNConstituents);
188  }
189 }
190 
195 {
196  std::map<std::string, AliJetInfo>::const_iterator it = fJets.find(n);
197  if (it == fJets.end()) return 0;
198 
199  Double_t z = 0;
200 
201  if ((*it).second.Pt() > 0) {
202  TVector3 dvect = fD.Vect();
203  TVector3 jvect = (*it).second.fMomentum.Vect();
204 
205  Double_t jetMom = jvect * jvect;
206 
207  if (jetMom < 1e-6) {
208  ::Error("AliAnalysisTaskDmesonJets::AliDmesonJetInfo::GetZ", "Zero jet momentum!");
209  z = 0.999;
210  }
211  else {
212  z = (dvect * jvect) / jetMom;
213  }
214 
215  if (z == 1 || (z > 1 && z - 1 < 1e-3)) z = 0.999; // so that it will contribute to the bin 0.9-1 rather than 1-1.1
216  }
217 
218  return z;
219 }
220 
225 {
226  std::map<std::string, AliJetInfo>::const_iterator it = fJets.find(n);
227  if (it == fJets.end()) return 0;
228 
229  Double_t z = 0;
230 
231  if ((*it).second.Pt() > 0) {
232  TVector3 dvect = fD.Vect();
233  TVector3 jvect = (*it).second.fMomentum.Vect();
234  // If the corr pt is < 0, assign 0.
235  Double_t corrpt = (*it).second.fCorrPt > 0 ? (*it).second.fCorrPt : 0.;
236  jvect.SetPerp(corrpt);
237 
238  Double_t jetMom = jvect * jvect;
239 
240  if (jetMom < 1e-6) {
241  z = 1.0;
242  }
243  else {
244  z = (dvect * jvect) / jetMom;
245  }
246  }
247 
248  return z;
249 }
250 
258 {
259  std::map<std::string, AliJetInfo>::const_iterator it = fJets.find(n);
260  if (it == fJets.end()) return 0;
261 
262  return GetDistance((*it).second, deta, dphi);
263 }
264 
270 {
271  Double_t deta = 0;
272  Double_t dphi = 0;
273  return GetDistance(n, deta, dphi);
274 }
275 
283 {
284  dphi = TVector2::Phi_mpi_pi(fD.Phi() - jet.Phi());;
285  deta = fD.Eta() - jet.Eta();
286  return TMath::Sqrt(dphi*dphi + deta*deta);
287 }
288 
294 {
295  Double_t deta = 0;
296  Double_t dphi = 0;
297  return GetDistance(jet, deta, dphi);
298 }
299 
305 {
306  std::map<std::string, AliJetInfo>::const_iterator it = fJets.find(n);
307  if (it == fJets.end()) {
308  ::Error("AliAnalysisTaskDmesonJets::AliDmesonJetInfo::GetJet", "Could not find jet info for the jet definition '%s'!",
309  n.c_str());
310  return 0;
311  }
312  return &((*it).second);
313 }
314 
320 {
321  std::map<std::string, AliJetInfo>::iterator it = fJets.find(n);
322  if (it == fJets.end()) {
323  ::Error("AliAnalysisTaskDmesonJets::AliDmesonJetInfo::GetJet", "Could not find jet info for the jet definition '%s'!",
324  n.c_str());
325  return 0;
326  }
327  return &((*it).second);
328 }
329 
330 // Definitions of class AliAnalysisTaskDmesonJets::AliJetInfoSummary
331 
335 
341  fPt(0),
342  fEta(0),
343  fPhi(0),
344  fR(0),
345  fZ(0),
346  fN(0)
347 {
348  Set(source, n);
349 }
350 
353 {
354  fPt = 0;
355  fEta = 0;
356  fPhi = 0;
357  fR = 0;
358  fZ = 0;
359  fN = 0;
360 }
361 
367 {
368  std::map<std::string, AliJetInfo>::const_iterator it = source.fJets.find(n);
369  if (it == source.fJets.end()) return;
370 
371  Set((*it).second);
372 
373  fR = source.GetDistance(n);
374  fZ = source.GetZ(n);
375 }
376 
381 {
382  fPt = source.Pt();
383  fEta = source.Eta();
384  fPhi = source.Phi_0_2pi();
385  fN = source.GetNConstituents();
386  fR = 0;
387  fZ = 0;
388 }
389 
390 // Definitions of class AliAnalysisTaskDmesonJets::AliJetInfoPbPbSummary
391 
395 
402  fCorrPt(0),
403  fCorrZ(0),
404  fArea(0)
405 {
406  Set(source, n);
407 }
408 
411 {
413  fCorrPt = 0;
414  fCorrZ = 0;
415  fArea = 0;
416 }
417 
422 {
423  AliJetInfoSummary::Set(source);
424  fArea = source.fArea;
425  fCorrPt = source.fCorrPt;
426 }
427 
433 {
434  AliJetInfoSummary::Set(source, n);
435  fCorrZ = source.GetCorrZ(n);
436 }
437 
438 // Definitions of class AliAnalysisTaskDmesonJets::AliDmesonInfoSummary
439 
443 
448  fPt(0),
449  fEta(0),
450  fPhi(0)
451 {
452  Set(source);
453 }
454 
459 {
460  fPt = source.fD.Pt();
461  fEta = source.fD.Eta();
462  fPhi = source.fD.Phi_0_2pi();
463 }
464 
467 {
468  fPt = 0;
469  fEta = 0;
470  fPhi = 0;
471 }
472 
473 // Definitions of class AliAnalysisTaskDmesonJets::AliDmesonMCInfoSummary
474 
478 
483  AliDmesonInfoSummary(source),
484  fPartonType(0),
485  fPartonPt(0),
486  fAncestorPDG(0)
487 {
488  Set(source);
489 }
490 
495 {
497 
498  fPartonType = source.fPartonType;
499 
500  if (source.fParton) {
501  fPartonPt = source.fParton->Pt();
502  }
503  else {
504  fPartonPt = 0.;
505  }
506 
507  if (source.fAncestor) {
508  fAncestorPDG = (UShort_t)((UInt_t)(TMath::Abs(source.fAncestor->GetPdgCode())));
509  }
510 }
511 
514 {
516  fPartonType = 0,
517  fPartonPt = 0.;
518  fAncestorPDG = 0;
519 }
520 
521 // Definitions of class AliAnalysisTaskDmesonJets::AliD0InfoSummary
522 
526 
531  AliDmesonInfoSummary(source),
532  fInvMass(source.fD.M()),
533  fSelectionType(0)
534 {
535 }
536 
541 {
542  fInvMass = source.fD.M();
545 }
546 
549 {
551  fSelectionType = 0;
552  fInvMass = 0;
553 }
554 
555 // Definitions of class AliAnalysisTaskDmesonJets::AliD0ExtendedInfoSummary
556 
560 
565  AliD0InfoSummary(source),
566  fDCA(0),
567  fCosThetaStar(0),
568  fd0K(0),
569  fd0Pi(0),
570  fd0d0(0),
571  fCosPointing(0),
572  fMaxNormd0(0)
573 {
574  Set(source);
575 }
576 
581 {
582  AliD0InfoSummary::Set(source);
583 
584  AliAODRecoDecayHF2Prong* recoDecay = dynamic_cast<AliAODRecoDecayHF2Prong*>(source.fDmesonParticle);
585  if (recoDecay) {
586  fDCA = recoDecay->GetDCA();
587  if (source.fSelectionType == 1) { // D0
588  fCosThetaStar = recoDecay->CosThetaStarD0();
589  fPtK = recoDecay->PtProng(0);
590  fPtPi = recoDecay->PtProng(1);
591  fd0K = recoDecay->Getd0Prong(0);
592  fd0Pi = recoDecay->Getd0Prong(1);
593  }
594  else { //D0bar
595  fCosThetaStar = recoDecay->CosThetaStarD0bar();
596  fPtK = recoDecay->PtProng(1);
597  fPtPi = recoDecay->PtProng(0);
598  fd0K = recoDecay->Getd0Prong(1);
599  fd0Pi = recoDecay->Getd0Prong(0);
600  }
601 
602  fMaxNormd0 = 0.;
603  // Based on Int_t AliRDHFCutsD0toKpi::IsSelected(TObject* obj,Int_t selectionLevel,AliAODEvent* aod)
604  // Line 480 and following
605  if (source.fEvent) {
606  for (Int_t ipr=0; ipr < 2; ipr++) {
607  Double_t diffIP = 0., errdiffIP = 0.;
608  recoDecay->Getd0MeasMinusExpProng(ipr, source.fEvent->GetMagneticField(), diffIP, errdiffIP);
609  Double_t normdd0 = 0.;
610  if (errdiffIP > 0.) {
611  normdd0 = diffIP / errdiffIP;
612  }
613  else {
614  if (diffIP == 0) {
615  normdd0 = 0;
616  }
617  else {
618  normdd0 = diffIP > 0 ? 9999. : -9999.;
619  }
620  }
621  if (TMath::Abs(normdd0) > TMath::Abs(fMaxNormd0)) {
622  fMaxNormd0 = normdd0;
623  }
624  }
625  }
626  else {
627  throw AliAnalysisTaskDmesonJets::AliEventNotFound("AliAnalysisTaskDmesonJets::AliDmesonJetInfo", "fEvent");
628  }
629 
630  fd0d0 = recoDecay->Prodd0d0();
631  fCosPointing = recoDecay->CosPointingAngle();
632  }
633 }
634 
637 {
639  fDCA = 0;
640  fCosThetaStar = 0;
641  fd0K = 0;
642  fd0Pi = 0;
643  fd0d0 = 0;
644  fCosPointing = 0;
645  fMaxNormd0 = 0;
646 }
647 
648 // Definitions of class AliAnalysisTaskDmesonJets::AliDStarInfoSummary
649 
653 
658  AliDmesonInfoSummary(source),
659  f2ProngInvMass(source.fInvMass2Prong),
660  fDeltaInvMass(source.fD.M() - source.fInvMass2Prong)
661 {
662 }
663 
668 {
670  fDeltaInvMass = source.fD.M() - source.fInvMass2Prong;
672 }
673 
676 {
678 
679  f2ProngInvMass = 0;
680  fDeltaInvMass = 0;
681 }
682 
683 // Definitions of class AliAnalysisTaskDmesonJets::AliJetDefinition
684 
688 
691  TObject(),
692  fJetType(AliJetContainer::kChargedJet),
693  fRadius(0),
694  fJetAlgo(AliJetContainer::antikt_algorithm),
695  fRecoScheme(AliJetContainer::pt_scheme),
696  fMinJetPt(0.),
697  fMaxJetPt(500.),
698  fMinJetPhi(0.),
699  fMaxJetPhi(0.),
700  fMinJetEta(-1.),
701  fMaxJetEta(1.),
702  fMinChargedPt(0.),
703  fMaxChargedPt(0.),
704  fMinNeutralPt(0.),
705  fMaxNeutralPt(0.),
706  fRhoName(),
707  fRho(0)
708 {
709 }
710 
718  TObject(),
719  fJetType(type),
720  fRadius(r),
721  fJetAlgo(algo),
722  fRecoScheme(reco),
723  fMinJetPt(0.),
724  fMaxJetPt(500.),
725  fMinJetPhi(0.),
726  fMaxJetPhi(0.),
727  fMinJetEta(-1.),
728  fMaxJetEta(1.),
729  fMinChargedPt(0.),
730  fMaxChargedPt(0.),
731  fMinNeutralPt(0.),
732  fMaxNeutralPt(0.),
733  fRhoName(),
734  fRho(0)
735 {
736 }
737 
745  TObject(),
746  fJetType(type),
747  fRadius(r),
748  fJetAlgo(algo),
749  fRecoScheme(reco),
750  fMinJetPt(0.),
751  fMaxJetPt(0.),
752  fMinJetPhi(0.),
753  fMaxJetPhi(0.),
754  fMinJetEta(0.),
755  fMaxJetEta(0.),
756  fMinChargedPt(0.),
757  fMaxChargedPt(0.),
758  fMinNeutralPt(0.),
759  fMaxNeutralPt(0.),
760  fRhoName(rhoName),
761  fRho(0)
762 {
763 }
764 
769  TObject(),
770  fJetType(source.fJetType),
771  fRadius(source.fRadius),
772  fJetAlgo(source.fJetAlgo),
773  fRecoScheme(source.fRecoScheme),
774  fMinJetPt(source.fMinJetPt),
775  fMaxJetPt(source.fMaxJetPt),
776  fMinJetPhi(source.fMinJetPhi),
777  fMaxJetPhi(source.fMaxJetPhi),
778  fMinJetEta(source.fMinJetEta),
779  fMaxJetEta(source.fMaxJetEta),
784  fRhoName(source.fRhoName),
785  fRho(0)
786 {
787 }
788 
793 {
794  new (this) AliHFJetDefinition(source);
795  return *this;
796 }
797 
800 {
801  static TString name;
802 
804 
805  return name.Data();
806 }
807 
813 {
814  if (fMinJetEta < fMaxJetEta && (jet.Eta() < fMinJetEta || jet.Eta() > fMaxJetEta)) return kFALSE;
815  if (fMinJetPhi < fMaxJetPhi && (jet.Phi() < fMinJetPhi || jet.Phi() > fMaxJetPhi)) return kFALSE;
816  if (fMinJetPt < fMaxJetPt && (jet.Pt() > fMaxJetPt || jet.Pt() < fMinJetPt)) return kFALSE;
817  if (fMinChargedPt < fMaxChargedPt && (jet.fMaxChargedPt < fMinChargedPt || jet.fMaxChargedPt > fMaxChargedPt)) return kFALSE;
818  if (fMinNeutralPt < fMaxNeutralPt && (jet.fMaxNeutralPt < fMinNeutralPt || jet.fMaxNeutralPt > fMaxNeutralPt)) return kFALSE;
819 
820  return kTRUE;
821 }
822 
828 {
829  const AliJetInfo* jet = dMesonJet.GetJet(n);
830  if (!jet) return kFALSE;
831  return IsJetInAcceptance((*jet));
832 }
833 
840 {
841  if (lhs.fJetType > rhs.fJetType) return false;
842  else if (lhs.fJetType < rhs.fJetType) return true;
843  else {
844  if (lhs.fRadius > rhs.fRadius) return false;
845  else if (lhs.fRadius < rhs.fRadius) return true;
846  else {
847  if (lhs.fJetAlgo > rhs.fJetAlgo) return false;
848  else if (lhs.fJetAlgo < rhs.fJetAlgo) return true;
849  else {
850  if (lhs.fRecoScheme < rhs.fRecoScheme) return true;
851  else return false;
852  }
853  }
854  }
855 }
856 
863 {
864  if (lhs.fJetType != rhs.fJetType) return false;
865  if (lhs.fRadius != rhs.fRadius) return false;
866  if (lhs.fJetAlgo != rhs.fJetAlgo) return false;
867  if (lhs.fRecoScheme != rhs.fRecoScheme) return false;
868  return true;
869 }
870 
871 // Definitions of class AliAnalysisTaskDmesonJets::AnalysisEngine
872 
876 
879  TObject(),
880  fPartons(),
881  fCandidateType(kD0toKpi),
882  fCandidateName(),
883  fCandidatePDG(0),
884  fNDaughters(0),
885  fPDGdaughters(),
886  fBranchName(),
887  fMCMode(kNoMC),
888  fNMassBins(0),
889  fMinMass(0),
890  fMaxMass(0),
891  fRDHFCuts(0),
892  fRejectedOrigin(0),
893  fAcceptedDecay(0),
894  fInhibit(kFALSE),
895  fJetDefinitions(),
896  fPtBinWidth(0.5),
897  fMaxPt(100),
898  fD0Extended(kFALSE),
899  fRandomGen(0),
900  fTrackEfficiency(0),
901  fRejectISR(kFALSE),
902  fDataSlotNumber(-1),
903  fTree(0),
904  fCurrentDmesonJetInfo(0),
905  fCurrentJetInfo(0),
906  fCandidateArray(0),
907  fMCContainer(),
908  fTrackContainers(),
909  fClusterContainers(),
910  fAodEvent(0),
911  fFastJetWrapper(0),
912  fHistManager(0),
913  fCent(-1)
914 {
915 }
916 
925  TObject(),
926  fPartons(),
927  fCandidateType(type),
928  fCandidateName(),
929  fCandidatePDG(0),
930  fNDaughters(0),
931  fPDGdaughters(),
932  fBranchName(),
933  fMCMode(MCmode),
934  fNMassBins(nMassBins),
935  fMinMass(0),
936  fMaxMass(0),
937  fRDHFCuts(cuts),
938  fRejectedOrigin(0),
940  fInhibit(kFALSE),
941  fJetDefinitions(),
942  fPtBinWidth(0.5),
943  fMaxPt(100),
944  fD0Extended(kFALSE),
945  fRandomGen(0),
946  fTrackEfficiency(0),
947  fDataSlotNumber(-1),
948  fTree(0),
950  fCurrentJetInfo(0),
951  fCandidateArray(0),
952  fMCContainer(),
955  fAodEvent(0),
956  fFastJetWrapper(0),
957  fHistManager(0),
958  fCent(-1)
959 {
960  SetCandidateProperties(range);
961 }
962 
967  TObject(source),
968  fPartons(source.fPartons),
972  fNDaughters(source.fNDaughters),
974  fBranchName(source.fBranchName),
975  fMCMode(source.fMCMode),
976  fNMassBins(source.fNMassBins),
977  fMinMass(source.fMinMass),
978  fMaxMass(source.fMaxMass),
979  fRDHFCuts(),
982  fInhibit(source.fInhibit),
984  fPtBinWidth(source.fPtBinWidth),
985  fMaxPt(source.fMaxPt),
986  fD0Extended(source.fD0Extended),
987  fRandomGen(source.fRandomGen),
989  fDataSlotNumber(-1),
990  fTree(0),
992  fCurrentJetInfo(0),
994  fMCContainer(source.fMCContainer),
997  fAodEvent(source.fAodEvent),
999  fHistManager(source.fHistManager),
1000  fCent(-1)
1001 {
1002  SetRDHFCuts(source.fRDHFCuts);
1003 }
1004 
1005 // Destructor
1007 {
1008  delete fRDHFCuts;
1009 }
1010 
1015 {
1016  new (this) AnalysisEngine(source);
1017  return *this;
1018 }
1019 
1024 {
1025  for (UInt_t i = 0; i < fJetDefinitions.size(); i++) {
1026  if (fJetDefinitions[i].IsJetInAcceptance(dMesonJet, fJetDefinitions[i].GetName())) return kTRUE;
1027  }
1028 
1029  return kFALSE;
1030 }
1031 
1033 void AliAnalysisTaskDmesonJets::AnalysisEngine::Init(const AliEMCALGeometry* const /*geom*/, Int_t /*runNumber*/)
1034 {
1035 }
1036 
1041 {
1042  switch (fCandidateType) {
1043  case kD0toKpi:
1044  fCandidatePDG = 421;
1045  fCandidateName = "D0";
1046  fNDaughters = 2;
1048  fPDGdaughters.Reset();
1049  fPDGdaughters[0] = 211; // pi
1050  fPDGdaughters[1] = 321; // K
1051  fBranchName = "D0toKpi";
1053  break;
1054  case kD0toKpiLikeSign:
1055  fCandidatePDG = 421;
1056  fCandidateName = "2ProngLikeSign";
1057  fNDaughters = 2;
1059  fPDGdaughters.Reset();
1060  fPDGdaughters[0] = 211; // pi
1061  fPDGdaughters[1] = 321; // K
1062  fBranchName = "LikeSign2Prong";
1063  break;
1064  case kDstartoKpipi:
1065  fCandidatePDG = 413;
1066  fCandidateName = "DStar";
1067  fNDaughters = 3;
1069  fPDGdaughters.Reset();
1070  fPDGdaughters[0] = 211; // pi soft
1071  fPDGdaughters[1] = 211; // pi fromD0
1072  fPDGdaughters[2] = 321; // K from D0
1073  fBranchName = "Dstar";
1075  break;
1076  default:
1077  ::Error("AliAnalysisTaskDmesonJets::AnalysisEngine::SetCandidateProperties","Candidate %d unknown!", fCandidateType);
1078  }
1079 
1081 }
1082 
1087 {
1088  if (fRDHFCuts) delete fRDHFCuts;
1089  fRDHFCuts = cuts;
1090 }
1091 
1096 {
1097  if (!cuts) return;
1098  if (fRDHFCuts) delete fRDHFCuts;
1099  fRDHFCuts = static_cast<AliRDHFCuts*>(cuts->Clone());
1100 }
1101 
1106 {
1107  static TString name;
1108 
1109  name = TString::Format("%s_%s", GetName(), jetDef.GetName());
1110 
1111  return name.Data();
1112 }
1113 
1118 {
1120  switch (fMCMode) {
1121  case kBackgroundOnly:
1122  fName += "_BackgroundOnly";
1123  break;
1124  case kSignalOnly:
1125  fName += "_SignalOnly";
1126  break;
1127  case kMCTruth:
1128  fName += "_MCTruth";
1129  break;
1130  case kD0Reflection:
1131  fName += "_D0Reflection";
1132  break;
1133  default:
1134  break;
1135  }
1136 
1137  if (fRDHFCuts) fName += TString::Format("_%s", fRDHFCuts->GetName());
1138 
1139  return fName.Data();
1140 }
1141 
1149 {
1150  std::vector<AliHFJetDefinition>::iterator it = FindJetDefinition(def);
1151 
1152  if (it == fJetDefinitions.end() || *it != def) { // No jet definition was found, adding a new one
1153  fJetDefinitions.push_back(def);
1154  ::Info("AliAnalysisTaskDmesonJets::AnalysisEngine::AddJetDefinition", "Jet definition '%s' has been added to analysis engine '%s'."
1155  "Total number of jet definitions is now %lu.",
1156  def.GetName(), GetName(), fJetDefinitions.size());
1157  // For detector level set maximum track pt to 100 GeV/c
1158  if (fMCMode != kMCTruth) fJetDefinitions[fJetDefinitions.size()-1].SetChargedPtRange(0., 100.);
1159  }
1160  else {
1161  ::Warning("AliAnalysisTaskDmesonJets::AnalysisEngine::AddJetDefinition", "The same jet definition '%s' was already added in analysis engine '%s'.", def.GetName(), GetName());
1162  }
1163 
1164  return &(*it);
1165 }
1166 
1178 {
1179  AliHFJetDefinition def(type, r, algo, reco);
1180 
1181  return AddJetDefinition(def);
1182 }
1183 
1189 std::vector<AliAnalysisTaskDmesonJets::AliHFJetDefinition>::iterator AliAnalysisTaskDmesonJets::AnalysisEngine::FindJetDefinition(const AliAnalysisTaskDmesonJets::AliHFJetDefinition& def)
1190 {
1191  std::vector<AliHFJetDefinition>::iterator it = fJetDefinitions.begin();
1192  while (it != fJetDefinitions.end() && (*it) != def) it++;
1193  return it;
1194 }
1195 
1200 {
1201  for (auto &jetdef : fJetDefinitions) jetdef.SetJetPhiRange(min, max);
1202 }
1203 
1208 {
1209  for (auto &jetdef : fJetDefinitions) jetdef.SetJetEtaRange(min, max);
1210 }
1211 
1216 {
1217  for (auto &jetdef : fJetDefinitions) jetdef.SetJetPtRange(min, max);
1218 }
1219 
1224 {
1225  for (auto &jetdef : fJetDefinitions) jetdef.SetChargedPtRange(min, max);
1226 }
1227 
1232 {
1233  for (auto &jetdef : fJetDefinitions) jetdef.SetNeutralPtRange(min, max);
1234 }
1235 
1242 {
1243  if (lhs.fCandidateType < rhs.fCandidateType) {
1244  return true;
1245  }
1246  else if (lhs.fCandidateType > rhs.fCandidateType) {
1247  return false;
1248  }
1249  else if (lhs.fMCMode < rhs.fMCMode) {
1250  return true;
1251  }
1252  else if (lhs.fMCMode > rhs.fMCMode) {
1253  return false;
1254  }
1255  else if (lhs.fRDHFCuts && !rhs.fRDHFCuts) {
1256  return true;
1257  }
1258  else if (lhs.fRDHFCuts && rhs.fRDHFCuts && strcmp(lhs.fRDHFCuts->GetName(), rhs.fRDHFCuts->GetName()) < 0) {
1259  return true;
1260  }
1261  else {
1262  return false;
1263  }
1264 }
1265 
1272 {
1273  if (lhs.fCandidateType != rhs.fCandidateType) return false;
1274  if (lhs.fMCMode != rhs.fMCMode) return false;
1275  if (lhs.fRDHFCuts == nullptr && rhs.fRDHFCuts != nullptr) return false;
1276  if (lhs.fRDHFCuts != nullptr && rhs.fRDHFCuts == nullptr) return false;
1277  if (lhs.fRDHFCuts && rhs.fRDHFCuts && strcmp(lhs.fRDHFCuts->GetName(), rhs.fRDHFCuts->GetName()) != 0) return false;
1278  return true;
1279 }
1280 
1289 {
1290  if (fCandidateType == kD0toKpi || fCandidateType == kD0toKpiLikeSign) { // D0 candidate
1291  return ExtractD0Attributes(Dcand, DmesonJet, i);
1292  }
1293  else if (fCandidateType == kDstartoKpipi) { // Dstar candidate
1294  return ExtractDstarAttributes(static_cast<const AliAODRecoCascadeHF*>(Dcand), DmesonJet, i);
1295  }
1296  else {
1297  return kFALSE;
1298  }
1299 }
1300 
1309 {
1310  AliDebug(10,"Checking if D0 meson is selected");
1311  Int_t isSelected = fRDHFCuts->IsSelected(const_cast<AliAODRecoDecayHF2Prong*>(Dcand), AliRDHFCuts::kAll, fAodEvent);
1312  if (isSelected == 0) return kFALSE;
1313 
1314  Int_t MCtruthPdgCode = 0;
1315 
1316  Double_t invMassD = 0;
1317 
1318  // If the analysis require knowledge of the MC truth, look for generated D meson matched to reconstructed candidate
1319  // Checks also the origin, and if it matches the rejected origin mask, return false
1321  Int_t mcLab = Dcand->MatchToMC(fCandidatePDG, fMCContainer->GetArray(), fNDaughters, fPDGdaughters.GetArray());
1322  DmesonJet.fMCLabel = mcLab;
1323 
1324  // Retrieve the generated particle (if exists) and its PDG code
1325  if (mcLab >= 0) {
1326  AliAODMCParticle* aodMcPart = static_cast<AliAODMCParticle*>(fMCContainer->GetArray()->At(mcLab));
1327 
1328  if (aodMcPart) {
1329  // Check origin and return false if it matches the rejected origin mask
1330  if (fRejectedOrigin) {
1331  auto origin = IsPromptCharm(aodMcPart, fMCContainer->GetArray());
1332  if ((origin.first & fRejectedOrigin) == origin.first) return kFALSE;
1333  }
1334  MCtruthPdgCode = aodMcPart->PdgCode();
1335  }
1336  }
1337  }
1338 
1339  if (isSelected == 1) { // selected as a D0
1340  if (i != 0) return kFALSE; // only one mass hypothesis thanks to PID
1341 
1342  if (fMCMode == kNoMC ||
1343  (MCtruthPdgCode == fCandidatePDG && fMCMode == kSignalOnly) ||
1344  (MCtruthPdgCode != fCandidatePDG && fMCMode == kBackgroundOnly) ||
1345  (MCtruthPdgCode == -fCandidatePDG && (fMCMode == kD0Reflection || fMCMode == kOnlyWrongPIDAccepted))) {
1346  // both background and signal are requested OR (it is a true D0 AND signal is requested) OR (it is NOT a D0 and background is requested)
1347  AliDebug(10,"Selected as D0");
1348  invMassD = Dcand->InvMassD0();
1349  }
1350  else { // conditions above not passed, so return FALSE
1351  return kFALSE;
1352  }
1353  }
1354  else if (isSelected == 2) { // selected as a D0bar
1355  if (i != 1) return kFALSE; // only one mass hypothesis thanks to PID
1356 
1357  if (fMCMode == kNoMC ||
1358  (MCtruthPdgCode == -fCandidatePDG && fMCMode == kSignalOnly) ||
1359  (MCtruthPdgCode != -fCandidatePDG && fMCMode == kBackgroundOnly) ||
1360  (MCtruthPdgCode == fCandidatePDG && (fMCMode == kD0Reflection || fMCMode == kOnlyWrongPIDAccepted))) {
1361  // both background and signal are requested OR (it is a true D0bar AND signal is requested) OR (it is NOT a D0bar and background is requested)
1362  AliDebug(10,"Selected as D0bar");
1363  invMassD = Dcand->InvMassD0bar();
1364  }
1365  else { // conditions above not passed, so return FALSE
1366  return kFALSE;
1367  }
1368  }
1369  else if (isSelected == 3) { // selected as either a D0bar or a D0 (PID on K and pi undecisive)
1370  AliDebug(10,"Selected as either D0 or D0bar");
1371 
1372  // Accept the correct mass hypothesis for signal-only and the wrong one for background-only
1373  if ((MCtruthPdgCode == fCandidatePDG && fMCMode == kSignalOnly) ||
1374  (MCtruthPdgCode == -fCandidatePDG && (fMCMode == kBackgroundOnly || fMCMode == kD0Reflection))) {
1375  if (i != 0) return kFALSE;
1376  AliDebug(10, "MC truth is D0");
1377  invMassD = Dcand->InvMassD0();
1378  }
1379  else if ((MCtruthPdgCode == -fCandidatePDG && fMCMode == kSignalOnly) ||
1380  (MCtruthPdgCode == fCandidatePDG && (fMCMode == kBackgroundOnly || fMCMode == kD0Reflection))) {
1381  if (i != 1) return kFALSE;
1382  AliDebug(10, "MC truth is D0bar");
1383  invMassD = Dcand->InvMassD0bar();
1384  }
1385  else { // (This candidate is neither a D0 nor a D0bar) OR (background-and-signal was requested)
1386 
1387  // Only accept it if background-only OR background-and-signal was requested
1388  if (fMCMode == kBackgroundOnly || fMCMode == kNoMC) {
1389  // Select D0 or D0bar depending on the i-parameter
1390  if (i == 0) {
1391  AliDebug(10, "Returning invariant mass with D0 hypothesis");
1392  invMassD = Dcand->InvMassD0();
1393  }
1394  else if (i == 1) {
1395  AliDebug(10, "Returning invariant mass with D0bar hypothesis");
1396  invMassD = Dcand->InvMassD0bar();
1397  }
1398  else { // i > 1
1399  return kFALSE;
1400  }
1401  }
1402  else { // signal-only was requested but this is not a true D0
1403  return kFALSE;
1404  }
1405  }
1406  }
1407  DmesonJet.fD.SetPtEtaPhiM(Dcand->Pt(), Dcand->Eta(), Dcand->Phi(), invMassD);
1408  return kTRUE;
1409 }
1410 
1419 {
1420  AliDebug(10,"Checking if D* meson is selected");
1421  Int_t isSelected = fRDHFCuts->IsSelected(const_cast<AliAODRecoCascadeHF*>(DstarCand), AliRDHFCuts::kAll, fAodEvent);
1422  if (isSelected == 0) return kFALSE;
1423 
1424  if ((i == 1 && DstarCand->Charge()>0) || (i == 0 && DstarCand->Charge()<0) || i > 1) return kFALSE; // only one mass hypothesis for the D*
1425 
1426  Int_t MCtruthPdgCode = 0;
1427 
1428  Double_t invMassD = 0;
1429 
1430  if (fMCMode == kBackgroundOnly || fMCMode == kSignalOnly) {
1431  Int_t pdgDgDStartoD0pi[2] = { 421, 211 }; // D0,pi
1432  Int_t pdgDgD0toKpi[2] = { 321, 211 }; // K, pi
1433 
1434  Int_t mcLab = DstarCand->MatchToMC(fCandidatePDG, 421, pdgDgDStartoD0pi, pdgDgD0toKpi, fMCContainer->GetArray());
1435  AliDebug(10, Form("MC label is %d", mcLab));
1436  DmesonJet.fMCLabel = mcLab;
1437  if (mcLab >= 0) {
1438  AliAODMCParticle* aodMcPart = static_cast<AliAODMCParticle*>(fMCContainer->GetArray()->At(mcLab));
1439 
1440  if (aodMcPart) {
1441  if (fRejectedOrigin) {
1442  auto origin = IsPromptCharm(aodMcPart, fMCContainer->GetArray());
1443  if ((origin.first & fRejectedOrigin) == origin.first) return kFALSE;
1444  }
1445 
1446  MCtruthPdgCode = aodMcPart->PdgCode();
1447  AliDebug(10, Form("MC truth pdg code is %d",MCtruthPdgCode));
1448  }
1449  }
1450  }
1451 
1452  Int_t absMCtruthPdgCode = TMath::Abs(MCtruthPdgCode);
1453  if (fMCMode == kNoMC ||
1454  (absMCtruthPdgCode == 413 && fMCMode == kSignalOnly) ||
1455  (absMCtruthPdgCode != 413 && fMCMode == kBackgroundOnly)) {
1456  // both background and signal are requested OR (it is a true D*/D*bar AND signal is requested) OR (it is NOT a D*/D*bar and background is requested)
1457  invMassD = DstarCand->InvMassDstarKpipi();
1458  DmesonJet.fSoftPionPt = DstarCand->GetBachelor()->Pt();
1459  DmesonJet.fInvMass2Prong = DstarCand->InvMassD0();
1460  DmesonJet.fD.SetPtEtaPhiM(DstarCand->Pt(), DstarCand->Eta(), DstarCand->Phi(), invMassD);
1461  return kTRUE;
1462  }
1463  else { // conditions above not passed, so return FALSE
1464  return kFALSE;
1465  }
1466 }
1467 
1475 {
1476  if (!part) return kUnknownDecay;
1477  if (!mcArray) return kUnknownDecay;
1478 
1480 
1481  Int_t absPdgPart = TMath::Abs(part->GetPdgCode());
1482 
1483  if (part->GetNDaughters() == 2) {
1484 
1485  AliAODMCParticle* d1 = static_cast<AliAODMCParticle*>(mcArray->At(part->GetDaughter(0)));
1486  AliAODMCParticle* d2 = static_cast<AliAODMCParticle*>(mcArray->At(part->GetDaughter(1)));
1487 
1488  if (!d1 || !d2) {
1489  return decay;
1490  }
1491 
1492  Int_t absPdg1 = TMath::Abs(d1->GetPdgCode());
1493  Int_t absPdg2 = TMath::Abs(d2->GetPdgCode());
1494 
1495  if (absPdgPart == 421) { // D0 -> K pi
1496  if ((absPdg1 == 211 && absPdg2 == 321) || // pi K
1497  (absPdg1 == 321 && absPdg2 == 211)) { // K pi
1498  decay = kDecayD0toKpi;
1499  }
1500  }
1501 
1502  if (absPdgPart == 413) { // D* -> D0 pi
1503  if (absPdg1 == 421 && absPdg2 == 211) { // D0 pi
1504  Int_t D0decay = CheckDecayChannel(d1, mcArray);
1505  if (D0decay == kDecayD0toKpi) {
1506  decay = kDecayDStartoKpipi;
1507  }
1508  }
1509  else if (absPdg1 == 211 && absPdg2 == 421) { // pi D0
1510  Int_t D0decay = CheckDecayChannel(d2, mcArray);
1511  if (D0decay == kDecayD0toKpi) {
1512  decay = kDecayDStartoKpipi;
1513  }
1514  }
1515  }
1516  }
1517 
1518  return decay;
1519 }
1520 
1527 std::pair<AliAnalysisTaskDmesonJets::EMesonOrigin_t, AliAODMCParticle*> AliAnalysisTaskDmesonJets::AnalysisEngine::IsPromptCharm(const AliAODMCParticle* part, TClonesArray* mcArray)
1528 {
1529  std::pair<AliAnalysisTaskDmesonJets::EMesonOrigin_t, AliAODMCParticle*> result(kUnknownQuark, 0);
1530 
1531  if (!part) return result;
1532  if (!mcArray) return result;
1533 
1534  static std::set<UInt_t> partons = { 4, 5 };
1535 
1536  AliAODMCParticle* parton = FindParticleOrigin(part, mcArray, kFindLast, partons);
1537  if (parton) {
1538  result.second = parton;
1539  UInt_t absPdgParton = TMath::Abs(parton->GetPdgCode());
1540  if (absPdgParton == 4) result.first = kFromCharm;
1541  else if (absPdgParton == 5) result.first = kFromBottom;
1542  }
1543 
1544  return result;
1545 }
1546 
1554 
1555 AliAODMCParticle* AliAnalysisTaskDmesonJets::AnalysisEngine::FindParticleOrigin(const AliAODMCParticle* part, TClonesArray* mcArray, EFindParticleOriginMode_t mode)
1556 {
1557  static std::set<UInt_t> pdgSet;
1558 
1559  return FindParticleOrigin(part, mcArray, mode, pdgSet);
1560 }
1561 
1570 
1571 AliAODMCParticle* AliAnalysisTaskDmesonJets::AnalysisEngine::FindParticleOrigin(const AliAODMCParticle* part, TClonesArray* mcArray, EFindParticleOriginMode_t mode, const std::set<UInt_t>& pdgSet)
1572 {
1573  AliAODMCParticle* result = nullptr;
1574 
1575  Int_t mother = part->GetMother();
1576  while (mother >= 0) {
1577  AliAODMCParticle* mcGranma = static_cast<AliAODMCParticle*>(mcArray->At(mother));
1578  if (mcGranma) {
1579  UInt_t abspdgGranma = TMath::Abs(mcGranma->GetPdgCode());
1580 
1581  // If the current particle is one of the particle types that is being searched assign it to the result pointer
1582  if (pdgSet.empty() || pdgSet.count(abspdgGranma) > 0) {
1583  result = mcGranma;
1584  // If the last particle in the fragmentation tree (first when going reverse) was requested then stop the loop
1585  if (mode == kFindLast) break;
1586  }
1587  if (mother == mcGranma->GetMother()) { // avoid infinite loop!
1588  AliWarningClassStream() << "Particle " << mother << " (PDG=" << mcGranma->PdgCode() << ") is the mother of itself!?" << std::endl;
1589  break;
1590  }
1591  mother = mcGranma->GetMother();
1592  }
1593  else {
1594  AliErrorClassStream() << "Could not retrieve mother particle " << mother << "!" << std::endl;
1595  break;
1596  }
1597  }
1598 
1599  return result;
1600 }
1601 
1604 {
1605  for (auto& jetDef : fJetDefinitions) {
1606  jetDef.fJets.clear();
1607  }
1608 
1609  if (fMCMode == kMCTruth) {
1611  }
1612  else {
1614  }
1615 }
1616 
1619 {
1620  // Fill the vertex info of the candidates
1621  // Needed for reduced delta AOD, where the vertex info has been deleted
1622  // to reduce the delta AOD file size
1624 
1625  const Int_t nD = fCandidateArray->GetEntriesFast();
1626 
1627  AliDmesonJetInfo DmesonJet;
1628  DmesonJet.fEvent = this->fAodEvent;
1629 
1630  std::map<AliHFJetDefinition*,Double_t> maxJetPt;
1631  for (auto& def : fJetDefinitions) maxJetPt[&def] = 0;
1632  Double_t maxDPt = 0;
1633 
1634  Int_t nAccCharm[3] = {0};
1635  for (Int_t icharm = 0; icharm < nD; icharm++) { //loop over D candidates
1636  AliAODRecoDecayHF2Prong* charmCand = static_cast<AliAODRecoDecayHF2Prong*>(fCandidateArray->At(icharm)); // D candidates
1637  if (!charmCand) continue;
1638  if(!(vHF.FillRecoCand(fAodEvent,charmCand))) continue;
1639 
1640  // region of interest + cuts
1641  if (!fRDHFCuts->IsInFiducialAcceptance(charmCand->Pt(), charmCand->Y(fCandidatePDG))) continue;
1642  Int_t nMassHypo = 0; // number of mass hypothesis accepted for this D meson
1643  if (charmCand->Pt() > maxDPt) maxDPt = charmCand->Pt();
1644  for (Int_t im = 0; im < 2; im++) { // 2 mass hypothesis (when available)
1645  DmesonJet.Reset();
1646  DmesonJet.fDmesonParticle = charmCand;
1647  DmesonJet.fSelectionType = im + 1;
1648  if (ExtractRecoDecayAttributes(charmCand, DmesonJet, im)) {
1649  for (auto& def : fJetDefinitions) {
1650  if (FindJet(charmCand, DmesonJet, def)) {
1651  Double_t jetPt = DmesonJet.fJets[def.GetName()].fMomentum.Pt();
1652  if (jetPt > maxJetPt[&def]) maxJetPt[&def] = jetPt;
1653  }
1654  else {
1655  AliWarning(Form("Could not find jet '%s' for D meson '%s': pT = %.3f, eta = %.3f, phi = %.3f",
1656  def.GetName(), GetName(), DmesonJet.fD.Pt(), DmesonJet.fD.Eta(), DmesonJet.fD.Phi_0_2pi()));
1657  }
1658  }
1659  fDmesonJets[(icharm+1)*(1-(im*2))] = DmesonJet;
1660  nMassHypo++;
1661  nAccCharm[im]++;
1662  }
1663  }
1664  if (nMassHypo == 2) {
1665  nAccCharm[0]--;
1666  nAccCharm[1]--;
1667  nAccCharm[2] += 2;
1668  }
1669  if (nMassHypo == 2) { // both mass hypothesis accepted
1670  fDmesonJets[(icharm+1)].fD0D0bar = kTRUE;
1671  fDmesonJets[-(icharm+1)].fD0D0bar = kTRUE;
1672  }
1673  } // end of D cand loop
1674 
1675  TString hname;
1676 
1677  Int_t ntracks = 0;
1678 
1679  for (auto track_cont : fTrackContainers) {
1680  AliHFTrackContainer* hftrack_cont = dynamic_cast<AliHFTrackContainer*>(track_cont);
1681  if (hftrack_cont) hftrack_cont->SetDMesonCandidate(nullptr);
1682  ntracks += track_cont->GetNAcceptEntries();
1683  }
1684 
1685  for (auto& def : fJetDefinitions) {
1686  if (!def.fRho) continue;
1687  hname = TString::Format("%s/%s/fHistRhoVsLeadJetPt", GetName(), def.GetName());
1688  fHistManager->FillTH2(hname, maxJetPt[&def], def.fRho->GetVal());
1689 
1690  hname = TString::Format("%s/%s/fHistRhoVsLeadDPt", GetName(), def.GetName());
1691  fHistManager->FillTH2(hname, maxDPt, def.fRho->GetVal());
1692 
1693  hname = TString::Format("%s/%s/fHistRhoVsCent", GetName(), def.GetName());
1694  fHistManager->FillTH2(hname, fCent, def.fRho->GetVal());
1695 
1696  hname = TString::Format("%s/%s/fHistLeadJetPtVsCent", GetName(), def.GetName());
1697  fHistManager->FillTH2(hname, fCent, maxJetPt[&def]);
1698 
1699  hname = TString::Format("%s/%s/fHistLeadDPtVsCent", GetName(), def.GetName());
1700  fHistManager->FillTH2(hname, fCent, maxDPt);
1701 
1702  hname = TString::Format("%s/%s/fHistRhoVsNTracks", GetName(), def.GetName());
1703  fHistManager->FillTH2(hname, ntracks, def.fRho->GetVal());
1704 
1705  hname = TString::Format("%s/%s/fHistLeadJetPtVsNTracks", GetName(), def.GetName());
1706  fHistManager->FillTH2(hname, ntracks, maxJetPt[&def]);
1707 
1708  hname = TString::Format("%s/%s/fHistLeadDPtVsNTracks", GetName(), def.GetName());
1709  fHistManager->FillTH2(hname, ntracks, maxDPt);
1710  }
1711 
1712  hname = TString::Format("%s/fHistNTotAcceptedDmesons", GetName());
1713  fHistManager->FillTH1(hname, "D", nAccCharm[0]);
1714  fHistManager->FillTH1(hname, "Anti-D", nAccCharm[1]);
1715  fHistManager->FillTH1(hname, "Both", nAccCharm[2]);
1716 
1717  hname = TString::Format("%s/fHistNAcceptedDmesonsVsNtracks", GetName());
1718  fHistManager->FillTH2(hname, ntracks, nAccCharm[0]+nAccCharm[1]+nAccCharm[2]);
1719 
1720  hname = TString::Format("%s/fHistNDmesons", GetName());
1721  fHistManager->FillTH1(hname, nD);
1722 }
1723 
1734 {
1735  TString hname;
1736 
1737  Double_t rho = 0;
1738  if (jetDef.fRho) rho = jetDef.fRho->GetVal();
1739 
1741  fFastJetWrapper->SetR(jetDef.fRadius);
1744 
1745  fFastJetWrapper->AddInputVector(DmesonJet.fD.Px(), DmesonJet.fD.Py(), DmesonJet.fD.Pz(), DmesonJet.fD.E(), 0);
1746 
1747  if (jetDef.fJetType != AliJetContainer::kNeutralJet) {
1748  for (auto track_cont : fTrackContainers) {
1749  AliHFTrackContainer* hftrack_cont = dynamic_cast<AliHFTrackContainer*>(track_cont);
1750  if (hftrack_cont) hftrack_cont->SetDMesonCandidate(Dcand);
1751  hname = TString::Format("%s/%s/fHistTrackRejectionReason", GetName(), jetDef.GetName());
1752  AddInputVectors(track_cont, 100, static_cast<TH2*>(fHistManager->FindObject(hname)), fTrackEfficiency);
1753 
1754  if (hftrack_cont) {
1755  hname = TString::Format("%s/%s/fHistDMesonDaughterNotInJet", GetName(), jetDef.GetName());
1756  TH1* histDaughterNotInJet = static_cast<TH1*>(fHistManager->FindObject(hname));
1757  const TObjArray& daughters = hftrack_cont->GetDaughterList();
1758  for (Int_t i = 0; i < daughters.GetEntriesFast(); i++) {
1759  AliVParticle* daughter = static_cast<AliVParticle*>(daughters.At(i));
1760  if (!hftrack_cont->GetArray()->FindObject(daughter)) histDaughterNotInJet->Fill(daughter->Pt());
1761  }
1762  }
1763  }
1764  }
1765 
1766  if (jetDef.fJetType != AliJetContainer::kChargedJet) {
1767  for (auto clus_cont : fClusterContainers) {
1768  hname = TString::Format("%s/%s/fHistClusterRejectionReason", GetName(), jetDef.GetName());
1769  AddInputVectors(clus_cont, -100, static_cast<TH2*>(fHistManager->FindObject(hname)));
1770  }
1771  }
1772 
1773  // run jet finder
1774  fFastJetWrapper->Run();
1775 
1776  std::vector<fastjet::PseudoJet> jets_incl = fFastJetWrapper->GetInclusiveJets();
1777 
1778  for (UInt_t ijet = 0; ijet < jets_incl.size(); ++ijet) {
1779  std::vector<fastjet::PseudoJet> constituents(fFastJetWrapper->GetJetConstituents(ijet));
1780 
1781  Bool_t isDmesonJet = kFALSE;
1782 
1783  Double_t maxChPt = 0;
1784  Double_t maxNePt = 0;
1785  Double_t totalNeutralPt = 0;
1786  Int_t nConst = 1;
1787 
1788  for (UInt_t ic = 0; ic < constituents.size(); ++ic) {
1789  if (constituents[ic].user_index() == 0) {
1790  isDmesonJet = kTRUE;
1791  }
1792  else if (constituents[ic].user_index() >= 100) {
1793  if (constituents[ic].pt() > maxChPt) maxChPt = constituents[ic].pt();
1794  nConst++;
1795  }
1796  else if (constituents[ic].user_index() <= -100) {
1797  totalNeutralPt += constituents[ic].pt();
1798  if (constituents[ic].pt() > maxNePt) maxChPt = constituents[ic].pt();
1799  nConst++;
1800  }
1801  }
1802 
1803  if (isDmesonJet) {
1804  DmesonJet.fJets[jetDef.GetName()].fMomentum.SetPxPyPzE(jets_incl[ijet].px(), jets_incl[ijet].py(), jets_incl[ijet].pz(), jets_incl[ijet].E());
1805  DmesonJet.fJets[jetDef.GetName()].fNConstituents = nConst;
1806  DmesonJet.fJets[jetDef.GetName()].fMaxChargedPt = maxChPt;
1807  DmesonJet.fJets[jetDef.GetName()].fMaxNeutralPt = maxNePt;
1808  DmesonJet.fJets[jetDef.GetName()].fNEF = totalNeutralPt / jets_incl[ijet].pt();
1809  DmesonJet.fJets[jetDef.GetName()].fArea = jets_incl[ijet].area();
1810  DmesonJet.fJets[jetDef.GetName()].fCorrPt = DmesonJet.fJets[jetDef.GetName()].fMomentum.Pt() - jets_incl[ijet].area() * rho;
1811 
1812  return kTRUE;
1813  }
1814  }
1815 
1816  return kFALSE;
1817 }
1818 
1822 void AliAnalysisTaskDmesonJets::AnalysisEngine::AddInputVectors(AliEmcalContainer* cont, Int_t offset, TH2* rejectHist, Double_t eff)
1823 {
1824  auto itcont = cont->all_momentum();
1825  for (AliEmcalIterableMomentumContainer::iterator it = itcont.begin(); it != itcont.end(); it++) {
1826  UInt_t rejectionReason = 0;
1827  if (!cont->AcceptObject(it.current_index(), rejectionReason)) {
1828  if (rejectHist) rejectHist->Fill(AliEmcalContainer::GetRejectionReasonBitPosition(rejectionReason), it->first.Pt());
1829  continue;
1830  }
1831  if (fRandomGen && eff > 0 && eff < 1) {
1832  Double_t rnd = fRandomGen->Rndm();
1833  if (eff < rnd) {
1834  if (rejectHist) rejectHist->Fill(6, it->first.Pt());
1835  continue;
1836  }
1837  }
1838  Int_t uid = offset >= 0 ? it.current_index() + offset: -it.current_index() - offset;
1839  fFastJetWrapper->AddInputVector(it->first.Px(), it->first.Py(), it->first.Pz(), it->first.E(), uid);
1840  }
1841 }
1842 
1845 {
1846  TString hname;
1847 
1852 
1853  if (!fMCContainer->IsSpecialPDGFound()) return;
1854 
1855  Int_t nAccCharm[3] = {0};
1856 
1857  std::map<AliHFJetDefinition*, Double_t> maxJetPt;
1858  Double_t maxDPt = 0;
1859 
1860  for (auto &jetDef : fJetDefinitions) {
1861  maxJetPt[&jetDef] = 0;
1862  Double_t rho = 0;
1863  if (jetDef.fRho) rho = jetDef.fRho->GetVal();
1864  hname = TString::Format("%s/%s/fHistNDmesonsVsNconstituents", GetName(), jetDef.GetName());
1865  TH1* histNDmesonsVsNconstituents = static_cast<TH1*>(fHistManager->FindObject(hname));
1866 
1867  switch (jetDef.fJetType) {
1869  fMCContainer->SetCharge(AliParticleContainer::EChargeCut_t::kNoChargeCut);
1870  break;
1872  fMCContainer->SetCharge(AliParticleContainer::EChargeCut_t::kCharged);
1873  break;
1875  fMCContainer->SetCharge(AliParticleContainer::EChargeCut_t::kNeutral);
1876  break;
1877  }
1878 
1880  fFastJetWrapper->SetR(jetDef.fRadius);
1883 
1884  hname = TString::Format("%s/%s/fHistMCParticleRejectionReason", GetName(), jetDef.GetName());
1885  AddInputVectors(fMCContainer, 100, static_cast<TH2*>(fHistManager->FindObject(hname)));
1886 
1887  fFastJetWrapper->Run();
1888 
1889  std::vector<fastjet::PseudoJet> jets_incl = fFastJetWrapper->GetInclusiveJets();
1890 
1891  for (auto jet : jets_incl) {
1892  Int_t nDmesonsInJet = 0;
1893 
1894  for (auto constituent : jet.constituents()) {
1895  Int_t iPart = constituent.user_index() - 100;
1896  if (constituent.perp() < 1e-6) continue; // reject ghost particles
1897  AliAODMCParticle* part = fMCContainer->GetMCParticle(iPart);
1898  if (!part) {
1899  ::Error("AliAnalysisTaskDmesonJets::AnalysisEngine::RunParticleLevelAnalysis", "Could not find jet constituent %d!", iPart);
1900  continue;
1901  }
1902  if (TMath::Abs(part->PdgCode()) == fCandidatePDG) {
1903  nDmesonsInJet++;
1904  std::map<int, AliDmesonJetInfo>::iterator dMesonJetIt = fDmesonJets.find(iPart);
1905  if (dMesonJetIt == fDmesonJets.end()) { // This D meson does not exist yet
1906  if (part->Pt() > maxDPt) maxDPt = part->Pt();
1907  std::pair<int, AliDmesonJetInfo> element;
1908  element.first = iPart;
1909  dMesonJetIt = fDmesonJets.insert(element).first;
1910  (*dMesonJetIt).second.fD.SetPxPyPzE(part->Px(), part->Py(), part->Pz(), part->E());
1911  (*dMesonJetIt).second.fDmesonParticle = part;
1912  (*dMesonJetIt).second.fSelectionType = part->PdgCode() > 0 ? 1 : 2;
1913 
1914  UShort_t p = 0;
1915  UInt_t rs = 0;
1916 
1917  auto origin = IsPromptCharm(part, fMCContainer->GetArray());
1918  p = 0;
1919  rs = origin.first;
1920  while (rs >>= 1) { p++; }
1921  (*dMesonJetIt).second.fPartonType = p;
1922  (*dMesonJetIt).second.fParton = origin.second;
1923 
1924  (*dMesonJetIt).second.fAncestor = FindParticleOrigin(part, fMCContainer->GetArray(), kFindFirst);
1925 
1926  if (part->PdgCode() > 0) { // D0
1927  nAccCharm[0]++;
1928  }
1929  else { // D0bar
1930  nAccCharm[1]++;
1931  }
1932  }
1933 
1934  (*dMesonJetIt).second.fJets[jetDef.GetName()].fMomentum.SetPxPyPzE(jet.px(), jet.py(), jet.pz(), jet.E());
1935  (*dMesonJetIt).second.fJets[jetDef.GetName()].fNConstituents = jet.constituents().size();
1936  (*dMesonJetIt).second.fJets[jetDef.GetName()].fArea = jet.area();
1937  (*dMesonJetIt).second.fJets[jetDef.GetName()].fCorrPt = (*dMesonJetIt).second.fJets[jetDef.GetName()].fMomentum.Pt() - jet.area() * rho;
1938  if (jet.perp() > maxJetPt[&jetDef]) maxJetPt[&jetDef] = jet.perp();
1939  } // if constituent is a D meson
1940  } // for each constituent
1941  if (nDmesonsInJet > 0) histNDmesonsVsNconstituents->Fill(jet.constituents().size(), nDmesonsInJet);
1942  } // for each jet
1943  } // for each jet definition
1944 
1946 
1947  for (auto& def : fJetDefinitions) {
1948  if (!def.fRho) continue;
1949  hname = TString::Format("%s/%s/fHistRhoVsLeadJetPt", GetName(), def.GetName());
1950  fHistManager->FillTH2(hname, maxJetPt[&def], def.fRho->GetVal());
1951 
1952  hname = TString::Format("%s/%s/fHistRhoVsLeadDPt", GetName(), def.GetName());
1953  fHistManager->FillTH2(hname, maxDPt, def.fRho->GetVal());
1954 
1955  hname = TString::Format("%s/%s/fHistRhoVsCent", GetName(), def.GetName());
1956  fHistManager->FillTH2(hname, fCent, def.fRho->GetVal());
1957 
1958  hname = TString::Format("%s/%s/fHistLeadJetPtVsCent", GetName(), def.GetName());
1959  fHistManager->FillTH2(hname, fCent, maxJetPt[&def]);
1960 
1961  hname = TString::Format("%s/%s/fHistLeadDPtVsCent", GetName(), def.GetName());
1962  fHistManager->FillTH2(hname, fCent, maxDPt);
1963 
1964  hname = TString::Format("%s/%s/fHistRhoVsNTracks", GetName(), def.GetName());
1965  fHistManager->FillTH2(hname, npart, def.fRho->GetVal());
1966 
1967  hname = TString::Format("%s/%s/fHistLeadJetPtVsNTracks", GetName(), def.GetName());
1968  fHistManager->FillTH2(hname, npart, maxJetPt[&def]);
1969 
1970  hname = TString::Format("%s/%s/fHistLeadDPtVsNTracks", GetName(), def.GetName());
1971  fHistManager->FillTH2(hname, npart, maxDPt);
1972  }
1973 
1974  if (fDmesonJets.size() != nAccCharm[0]+nAccCharm[1]) AliError(Form("I found %lu mesons (%d)?", fDmesonJets.size(), nAccCharm[0]+nAccCharm[1]));
1975  hname = TString::Format("%s/fHistNTotAcceptedDmesons", GetName());
1976  fHistManager->FillTH1(hname, "D", nAccCharm[0]);
1977  fHistManager->FillTH1(hname, "Anti-D", nAccCharm[1]);
1978  fHistManager->FillTH1(hname, "Both", nAccCharm[2]);
1979 
1980  hname = TString::Format("%s/fHistNAcceptedDmesonsVsNtracks", GetName());
1981  fHistManager->FillTH2(hname, npart, nAccCharm[0]+nAccCharm[1]+nAccCharm[2]);
1982 
1983  hname = TString::Format("%s/fHistNDmesons", GetName());
1984  fHistManager->FillTH1(hname, nAccCharm[0]+nAccCharm[1]+nAccCharm[2]); // same as the number of accepted D mesons, since no selection is performed
1985 }
1986 
1991 {
1992  TString classname;
1993  if (fMCMode == kMCTruth) {
1994  classname = "AliAnalysisTaskDmesonJets::AliDmesonMCInfoSummary";
1996  }
1997  else {
1998  switch (fCandidateType) {
1999  case kD0toKpi:
2000  case kD0toKpiLikeSign:
2001  if (fD0Extended) {
2002  classname = "AliAnalysisTaskDmesonJets::AliD0ExtendedInfoSummary";
2004  }
2005  else {
2006  classname = "AliAnalysisTaskDmesonJets::AliD0InfoSummary";
2008  }
2009  break;
2010  case kDstartoKpipi:
2011  classname = "AliAnalysisTaskDmesonJets::AliDStarInfoSummary";
2013  break;
2014  }
2015  }
2016  TString treeName = TString::Format("%s_%s", taskName, GetName());
2017  fTree = new TTree(treeName, treeName);
2018  fTree->Branch("DmesonJet", classname, &fCurrentDmesonJetInfo);
2020  for (Int_t i = 0; i < fJetDefinitions.size(); i++) {
2021  if (fJetDefinitions[i].fRhoName.IsNull()) {
2023  fTree->Branch(fJetDefinitions[i].GetName(), "AliAnalysisTaskDmesonJets::AliJetInfoSummary", &fCurrentJetInfo[i]);
2024  }
2025  else {
2027  fTree->Branch(fJetDefinitions[i].GetName(), "AliAnalysisTaskDmesonJets::AliJetInfoPbPbSummary", &fCurrentJetInfo[i]);
2028  }
2029  }
2030 
2031  return fTree;
2032 }
2033 
2038 {
2039  TString hname;
2040 
2041  Int_t nPtBins = TMath::CeilNint(fMaxPt / fPtBinWidth);
2042 
2043  for (auto &jetDef : fJetDefinitions) {
2044 
2045  AliDebug(2,Form("Now working on '%s'", jetDef.GetName()));
2046 
2047  Double_t radius = jetDef.fRadius;
2048 
2049  TString title[30] = {""};
2050  Int_t nbins[30] = {0 };
2051  Double_t min [30] = {0.};
2052  Double_t max [30] = {0.};
2053  Int_t dim = 0 ;
2054 
2055  title[dim] = "#it{p}_{T,D} (GeV/#it{c})";
2056  nbins[dim] = nPtBins;
2057  min[dim] = 0;
2058  max[dim] = fMaxPt;
2059  dim++;
2060 
2061  if ((enabledAxis & kPositionD) != 0) {
2062  title[dim] = "#eta_{D}";
2063  nbins[dim] = 50;
2064  min[dim] = -1;
2065  max[dim] = 1;
2066  dim++;
2067 
2068  title[dim] = "#phi_{D} (rad)";
2069  nbins[dim] = 150;
2070  min[dim] = 0;
2071  max[dim] = TMath::TwoPi();
2072  dim++;
2073  }
2074 
2075  if ((enabledAxis & kInvMass) != 0 && fCandidateType == kDstartoKpipi) {
2076  title[dim] = "#it{M}_{K#pi#pi} (GeV/#it{c}^{2})";
2077  nbins[dim] = fNMassBins;
2078  min[dim] = fMinMass;
2079  max[dim] = fMaxMass;
2080  dim++;
2081  }
2082 
2084  title[dim] = "#it{M}_{K#pi} (GeV/#it{c}^{2})";
2085  nbins[dim] = fNMassBins;
2086  min[dim] = fMinMass;
2087  max[dim] = fMaxMass;
2088  dim++;
2089  }
2090 
2091  if ((enabledAxis & k2ProngInvMass) != 0 && fCandidateType == kDstartoKpipi) {
2092  title[dim] = "#it{M}_{K#pi} (GeV/#it{c}^{2})";
2093  nbins[dim] = fNMassBins;
2094  CalculateMassLimits(fMaxMass - fMinMass, 421, fNMassBins, min[dim], max[dim]);
2095  dim++;
2096  }
2097 
2098  if (fCandidateType == kDstartoKpipi) {
2099  title[dim] = "#it{M}_{K#pi#pi} - #it{M}_{K#pi} (GeV/#it{c}^{2})";
2100  nbins[dim] = fNMassBins*6;
2101  CalculateMassLimits(0.20, 413, nbins[dim], min[dim], max[dim]);
2102 
2103  // subtract mass of D0
2104  Double_t D0mass = TDatabasePDG::Instance()->GetParticle(421)->Mass();
2105  min[dim] -= D0mass;
2106  max[dim] -= D0mass;
2107 
2108  dim++;
2109  }
2110 
2111  if ((enabledAxis & kSoftPionPt) != 0 && fCandidateType == kDstartoKpipi) {
2112  title[dim] = "#it{p}_{T,#pi} (GeV/#it{c})";
2113  nbins[dim] = 100;
2114  min[dim] = 0;
2115  max[dim] = 25;
2116  dim++;
2117  }
2118 
2119  title[dim] = "#it{z}_{D}";
2120  nbins[dim] = 110;
2121  min[dim] = 0;
2122  max[dim] = 1.10;
2123  dim++;
2124 
2125  if ((enabledAxis & kDeltaR) != 0) {
2126  title[dim] = "#Delta R_{D-jet}";
2127  nbins[dim] = 100;
2128  min[dim] = 0;
2129  max[dim] = radius * 1.5;
2130  dim++;
2131  }
2132 
2133  if ((enabledAxis & kDeltaEta) != 0) {
2134  title[dim] = "#eta_{D} - #eta_{jet}";
2135  nbins[dim] = 100;
2136  min[dim] = -radius * 1.2;
2137  max[dim] = radius * 1.2;
2138  dim++;
2139  }
2140 
2141  if ((enabledAxis & kDeltaPhi) != 0) {
2142  title[dim] = "#phi_{D} - #phi_{jet} (rad)";
2143  nbins[dim] = 100;
2144  min[dim] = -radius * 1.2;
2145  max[dim] = radius * 1.2;
2146  dim++;
2147  }
2148 
2149  title[dim] = "#it{p}_{T,jet} (GeV/#it{c})";
2150  nbins[dim] = nPtBins;
2151  min[dim] = 0;
2152  max[dim] = fMaxPt;
2153  dim++;
2154 
2155  if ((enabledAxis & kPositionJet) != 0) {
2156  title[dim] = "#eta_{jet}";
2157  nbins[dim] = 50;
2158  min[dim] = -1;
2159  max[dim] = 1;
2160  dim++;
2161 
2162  title[dim] = "#phi_{jet} (rad)";
2163  nbins[dim] = 150;
2164  min[dim] = 0;
2165  max[dim] = TMath::TwoPi();
2166  dim++;
2167  }
2168 
2169  if ((enabledAxis & kJetConstituents) != 0) {
2170  title[dim] = "No. of constituents";
2171  nbins[dim] = 50;
2172  min[dim] = -0.5;
2173  max[dim] = 49.5;
2174  dim++;
2175  }
2176 
2177  hname = TString::Format("%s/%s/fDmesonJets", GetName(), jetDef.GetName());
2178  THnSparse* h = fHistManager->CreateTHnSparse(hname,hname,dim,nbins,min,max);
2179  for (Int_t j = 0; j < dim; j++) {
2180  h->GetAxis(j)->SetTitle(title[j]);
2181  }
2182  }
2183 }
2184 
2189 {
2190  TString hname;
2191  fPartons.clear();
2192 
2193  TH1* histAncestor = nullptr;
2194  TH1* histPrompt = nullptr;
2195 
2196  if (fMCMode == kSignalOnly || fMCMode == kMCTruth) {
2197  hname = TString::Format("%s/fHistPrompt", GetName());
2198  histPrompt = static_cast<TH1*>(fHistManager->FindObject(hname));
2199 
2200  hname = TString::Format("%s/fHistAncestor", GetName());
2201  histAncestor = static_cast<TH1*>(fHistManager->FindObject(hname));
2202  }
2203 
2204  for (auto& dmeson_pair : fDmesonJets) {
2205  fCurrentDmesonJetInfo->Set(dmeson_pair.second);
2206  Int_t accJets = 0;
2207  for (UInt_t ij = 0; ij < fJetDefinitions.size(); ij++) {
2208  fCurrentJetInfo[ij]->Reset();
2209  AliJetInfo* jet = dmeson_pair.second.GetJet(fJetDefinitions[ij].GetName());
2210  if (!jet) continue;
2211  if (applyKinCuts && !fJetDefinitions[ij].IsJetInAcceptance(*jet)) {
2212  hname = TString::Format("%s/%s/fHistRejectedJetPt", GetName(), fJetDefinitions[ij].GetName());
2213  fHistManager->FillTH1(hname, jet->Pt());
2214  hname = TString::Format("%s/%s/fHistRejectedJetPhi", GetName(), fJetDefinitions[ij].GetName());
2215  fHistManager->FillTH1(hname, jet->Phi_0_2pi());
2216  hname = TString::Format("%s/%s/fHistRejectedJetEta", GetName(), fJetDefinitions[ij].GetName());
2217  fHistManager->FillTH1(hname, jet->Eta());
2218  continue;
2219  }
2220  fCurrentJetInfo[ij]->Set(dmeson_pair.second, fJetDefinitions[ij].GetName());
2221  accJets++;
2222  }
2223  if (accJets > 0) {
2224  if (histPrompt) {
2225  if (dmeson_pair.second.fParton) {
2226  fPartons[dmeson_pair.second.fParton] = dmeson_pair.second.fPartonType;
2227  UInt_t absPdgParton = TMath::Abs(dmeson_pair.second.fParton->GetPdgCode());
2228  if (absPdgParton == 4) {
2229  histPrompt->Fill("Prompt", 1);
2230  }
2231  else if (absPdgParton == 5) {
2232  histPrompt->Fill("Non-Prompt", 1);
2233  }
2234  else {
2235  histPrompt->Fill("Unknown", 1);
2236  }
2237  }
2238  else {
2239  histPrompt->Fill("Unknown", 1);
2240  }
2241  }
2242 
2243  if (histAncestor) {
2244  if (dmeson_pair.second.fAncestor) {
2245  UInt_t absPdgAncestor = TMath::Abs(dmeson_pair.second.fAncestor->GetPdgCode());
2246  if (absPdgAncestor == 4) {
2247  histAncestor->Fill("Charm", 1);
2248  }
2249  else if (absPdgAncestor == 5) {
2250  histAncestor->Fill("Bottom", 1);
2251  }
2252  else if (absPdgAncestor == 2212) {
2253  histAncestor->Fill("Proton", 1);
2254  }
2255  else {
2256  histAncestor->Fill("Unknown", 1);
2257  }
2258  }
2259  else {
2260  histAncestor->Fill("Unknown", 1);
2261  }
2262  }
2263 
2264  fTree->Fill();
2265  }
2266  else {
2267  hname = TString::Format("%s/fHistRejectedDMesonPt", GetName());
2268  fHistManager->FillTH1(hname, dmeson_pair.second.fD.Pt());
2269  hname = TString::Format("%s/fHistRejectedDMesonPhi", GetName());
2270  fHistManager->FillTH1(hname, dmeson_pair.second.fD.Phi_0_2pi());
2271  hname = TString::Format("%s/fHistRejectedDMesonEta", GetName());
2272  fHistManager->FillTH1(hname, dmeson_pair.second.fD.Eta());
2273  if (fMCMode != kMCTruth) {
2275  hname = TString::Format("%s/fHistRejectedDMesonInvMass", GetName());
2276  fHistManager->FillTH1(hname, dmeson_pair.second.fD.M());
2277  }
2278  else if (fCandidateType == kDstartoKpipi) {
2279  hname = TString::Format("%s/fHistRejectedDMeson2ProngInvMass", GetName());
2280  fHistManager->FillTH1(hname, dmeson_pair.second.fInvMass2Prong);
2281 
2282  hname = TString::Format("%s/fHistRejectedDMesonDeltaInvMass", GetName());
2283  fHistManager->FillTH1(hname, dmeson_pair.second.fD.M() - dmeson_pair.second.fInvMass2Prong);
2284  }
2285  }
2286  }
2287  }
2288 
2289  if (fMCMode == kSignalOnly || fMCMode == kMCTruth) {
2290  hname = TString::Format("%s/fHistPartonPt", GetName());
2291  TH1* histPartonPt = static_cast<TH1*>(fHistManager->FindObject(hname));
2292  hname = TString::Format("%s/fHistPartonEta", GetName());
2293  TH1* histPartonEta = static_cast<TH1*>(fHistManager->FindObject(hname));
2294  hname = TString::Format("%s/fHistPartonPhi", GetName());
2295  TH1* histPartonPhi = static_cast<TH1*>(fHistManager->FindObject(hname));
2296  hname = TString::Format("%s/fHistPartonType", GetName());
2297  TH1* histPartonType = static_cast<TH1*>(fHistManager->FindObject(hname));
2298 
2299  for (auto parton : fPartons) {
2300  if (!parton.first) continue;
2301  histPartonPt->Fill(parton.first->Pt());
2302  histPartonEta->Fill(parton.first->Eta());
2303  histPartonPhi->Fill(TVector2::Phi_0_2pi(parton.first->Phi()));
2304  histPartonType->Fill(parton.second);
2305  }
2306  }
2307 
2308  return kTRUE;
2309 }
2310 
2316 {
2317  TString hname;
2318 
2319  TH1* histAncestor = nullptr;
2320  TH1* histPrompt = nullptr;
2321 
2322  if (fMCMode == kSignalOnly || fMCMode == kMCTruth) {
2323  hname = TString::Format("%s/fHistPrompt", GetName());
2324  histPrompt = static_cast<TH1*>(fHistManager->FindObject(hname));
2325 
2326  hname = TString::Format("%s/fHistAncestor", GetName());
2327  histAncestor = static_cast<TH1*>(fHistManager->FindObject(hname));
2328  }
2329 
2330  fPartons.clear();
2331  for (auto& dmeson_pair : fDmesonJets) {
2332  Int_t accJets = 0;
2333  for (UInt_t ij = 0; ij < fJetDefinitions.size(); ij++) {
2334  AliJetInfo* jet = dmeson_pair.second.GetJet(fJetDefinitions[ij].GetName());
2335  if (!jet) continue;
2336  if (applyKinCuts && !fJetDefinitions[ij].IsJetInAcceptance(*jet)) {
2337  hname = TString::Format("%s/%s/fHistRejectedJetPt", GetName(), fJetDefinitions[ij].GetName());
2338  fHistManager->FillTH1(hname, jet->Pt());
2339  hname = TString::Format("%s/%s/fHistRejectedJetPhi", GetName(), fJetDefinitions[ij].GetName());
2340  fHistManager->FillTH1(hname, jet->Phi_0_2pi());
2341  hname = TString::Format("%s/%s/fHistRejectedJetEta", GetName(), fJetDefinitions[ij].GetName());
2342  fHistManager->FillTH1(hname, jet->Eta());
2343  continue;
2344  }
2345  accJets++;
2346  }
2347  if (accJets > 0) {
2348  if (histPrompt) {
2349  if (dmeson_pair.second.fParton) {
2350  fPartons[dmeson_pair.second.fParton] = dmeson_pair.second.fPartonType;
2351  UInt_t absPdgParton = TMath::Abs(dmeson_pair.second.fParton->GetPdgCode());
2352  if (absPdgParton == 4) {
2353  histPrompt->Fill("Prompt", 1);
2354  }
2355  else if (absPdgParton == 5) {
2356  histPrompt->Fill("Non-Prompt", 1);
2357  }
2358  else {
2359  histPrompt->Fill("Unknown", 1);
2360  }
2361  }
2362  else {
2363  histPrompt->Fill("Unknown", 1);
2364  }
2365  }
2366 
2367  if (histAncestor) {
2368  if (dmeson_pair.second.fAncestor) {
2369  UInt_t absPdgAncestor = TMath::Abs(dmeson_pair.second.fAncestor->GetPdgCode());
2370  if (absPdgAncestor == 4) {
2371  histAncestor->Fill("Charm", 1);
2372  }
2373  else if (absPdgAncestor == 5) {
2374  histAncestor->Fill("Bottom", 1);
2375  }
2376  else if (absPdgAncestor == 2212) {
2377  histAncestor->Fill("Proton", 1);
2378  }
2379  else {
2380  histAncestor->Fill("Unknown", 1);
2381  }
2382  }
2383  else {
2384  histAncestor->Fill("Unknown", 1);
2385  }
2386  }
2387  }
2388  else {
2389  hname = TString::Format("%s/fHistRejectedDMesonPt", GetName());
2390  fHistManager->FillTH1(hname, dmeson_pair.second.fD.Pt());
2391  hname = TString::Format("%s/fHistRejectedDMesonPhi", GetName());
2392  fHistManager->FillTH1(hname, dmeson_pair.second.fD.Phi_0_2pi());
2393  hname = TString::Format("%s/fHistRejectedDMesonEta", GetName());
2394  fHistManager->FillTH1(hname, dmeson_pair.second.fD.Eta());
2395  if (fMCMode != kMCTruth) {
2397  hname = TString::Format("%s/fHistRejectedDMesonInvMass", GetName());
2398  fHistManager->FillTH1(hname, dmeson_pair.second.fD.M());
2399  }
2400  else if (fCandidateType == kDstartoKpipi) {
2401  hname = TString::Format("%s/fHistRejectedDMeson2ProngInvMass", GetName());
2402  fHistManager->FillTH1(hname, dmeson_pair.second.fInvMass2Prong);
2403 
2404  hname = TString::Format("%s/fHistRejectedDMesonDeltaInvMass", GetName());
2405  fHistManager->FillTH1(hname, dmeson_pair.second.fD.M() - dmeson_pair.second.fInvMass2Prong);
2406  }
2407  }
2408  }
2409  }
2410 
2411  if (fMCMode == kSignalOnly || fMCMode == kMCTruth) {
2412  hname = TString::Format("%s/fHistPartonPt", GetName());
2413  TH1* histPartonPt = static_cast<TH1*>(fHistManager->FindObject(hname));
2414  hname = TString::Format("%s/fHistPartonEta", GetName());
2415  TH1* histPartonEta = static_cast<TH1*>(fHistManager->FindObject(hname));
2416  hname = TString::Format("%s/fHistPartonPhi", GetName());
2417  TH1* histPartonPhi = static_cast<TH1*>(fHistManager->FindObject(hname));
2418  hname = TString::Format("%s/fHistPartonType", GetName());
2419  TH1* histPartonType = static_cast<TH1*>(fHistManager->FindObject(hname));
2420 
2421  for (auto parton : fPartons) {
2422  if (!parton.first) continue;
2423  histPartonPt->Fill(parton.first->Pt());
2424  histPartonEta->Fill(parton.first->Eta());
2425  histPartonPhi->Fill(TVector2::Phi_0_2pi(parton.first->Phi()));
2426  histPartonType->Fill(parton.second);
2427  }
2428  }
2429 
2430  return kTRUE;
2431 }
2432 
2437 {
2438  TString hname;
2439 
2440  for (auto& dmeson_pair : fDmesonJets) {
2441  if (!IsAnyJetInAcceptance(dmeson_pair.second)) {
2442  hname = TString::Format("%s/fHistRejectedDMesonPt", GetName());
2443  fHistManager->FillTH1(hname, dmeson_pair.second.fD.Pt());
2444  hname = TString::Format("%s/fHistRejectedDMesonPhi", GetName());
2445  fHistManager->FillTH1(hname, dmeson_pair.second.fD.Phi_0_2pi());
2446  hname = TString::Format("%s/fHistRejectedDMesonEta", GetName());
2447  fHistManager->FillTH1(hname, dmeson_pair.second.fD.Eta());
2448  }
2449  }
2450 
2451  for (auto &jetDef : fJetDefinitions) {
2452 
2453  hname = TString::Format("%s/%s/fDmesonJets", GetName(), jetDef.GetName());
2454  THnSparse* h = static_cast<THnSparse*>(fHistManager->FindObject(hname));
2455 
2456  for (auto& dmeson_pair : fDmesonJets) {
2457  const AliJetInfo* jet = dmeson_pair.second.GetJet(jetDef.GetName());
2458  if (!jet) continue;
2459  if (!jetDef.IsJetInAcceptance(*jet)) {
2460  hname = TString::Format("%s/%s/fHistRejectedJetPt", GetName(), jetDef.GetName());
2461  fHistManager->FillTH1(hname, jet->Pt());
2462  hname = TString::Format("%s/%s/fHistRejectedJetPhi", GetName(), jetDef.GetName());
2463  fHistManager->FillTH1(hname, jet->Phi_0_2pi());
2464  hname = TString::Format("%s/%s/fHistRejectedJetEta", GetName(), jetDef.GetName());
2465  fHistManager->FillTH1(hname, jet->Eta());
2466  continue;
2467  }
2468  FillHnSparse(h, dmeson_pair.second, jetDef.GetName());
2469  }
2470  }
2471 
2472  return kTRUE;
2473 }
2474 
2481 {
2482  // Fill the THnSparse histogram.
2483 
2484  Double_t contents[30] = {0.};
2485 
2486  Double_t z = DmesonJet.GetZ(n);
2487  Double_t deltaPhi = 0;
2488  Double_t deltaEta = 0;
2489  Double_t deltaR = DmesonJet.GetDistance(n, deltaEta, deltaPhi);
2490 
2491  std::map<std::string, AliJetInfo>::const_iterator it = DmesonJet.fJets.find(n);
2492  if (it == DmesonJet.fJets.end()) return kFALSE;
2493 
2494  for (Int_t i = 0; i < h->GetNdimensions(); i++) {
2495  TString title(h->GetAxis(i)->GetTitle());
2496  if (title=="#it{p}_{T,D} (GeV/#it{c})") contents[i] = DmesonJet.fD.Pt();
2497  else if (title=="#eta_{D}") contents[i] = DmesonJet.fD.Eta();
2498  else if (title=="#phi_{D} (rad)") contents[i] = DmesonJet.fD.Phi_0_2pi();
2499  else if (title=="#it{M}_{K#pi} (GeV/#it{c}^{2})") contents[i] = DmesonJet.fInvMass2Prong > 0 ? DmesonJet.fInvMass2Prong : DmesonJet.fD.M();
2500  else if (title=="#it{M}_{K#pi#pi} (GeV/#it{c}^{2})") contents[i] = DmesonJet.fD.M();
2501  else if (title=="#it{M}_{K#pi#pi} - #it{M}_{K#pi} (GeV/#it{c}^{2})") contents[i] = DmesonJet.fD.M() - DmesonJet.fInvMass2Prong;
2502  else if (title=="#it{p}_{T,#pi} (GeV/#it{c})") contents[i] = DmesonJet.fSoftPionPt;
2503  else if (title=="#it{z}_{D}") contents[i] = z;
2504  else if (title=="#Delta R_{D-jet}") contents[i] = deltaR;
2505  else if (title=="#eta_{D} - #eta_{jet}") contents[i] = deltaEta;
2506  else if (title=="#phi_{D} - #phi_{jet} (rad)") contents[i] = deltaPhi;
2507  else if (title=="#it{p}_{T,jet} (GeV/#it{c})") contents[i] = (*it).second.Pt();
2508  else if (title=="#eta_{jet}") contents[i] = (*it).second.Eta();
2509  else if (title=="#phi_{jet} (rad)") contents[i] = (*it).second.Phi_0_2pi();
2510  else if (title=="No. of constituents") contents[i] = (*it).second.fNConstituents;
2511  else AliWarning(Form("Unable to fill dimension '%s'!",title.Data()));
2512  }
2513 
2514  h->Fill(contents);
2515 
2516  return kTRUE;
2517 }
2518 
2519 // Definitions of class AliAnalysisTaskDmesonJets
2520 
2522 ClassImp(AliAnalysisTaskDmesonJets);
2524 
2528  fAnalysisEngines(),
2529  fEnabledAxis(0),
2531  fHistManager(),
2532  fApplyKinematicCuts(kTRUE),
2533  fNOutputTrees(0),
2534  fTrackEfficiency(0),
2535  fRejectISR(kFALSE),
2536  fJetAreaType(fastjet::active_area),
2537  fJetGhostArea(0.005),
2538  fMCContainer(0),
2539  fAodEvent(0),
2540  fFastJetWrapper(0)
2541 {
2542  SetMakeGeneralHistograms(kTRUE);
2543 }
2544 
2549  AliAnalysisTaskEmcalLight(name, kTRUE),
2550  fAnalysisEngines(),
2553  fHistManager(name),
2554  fApplyKinematicCuts(kTRUE),
2555  fNOutputTrees(nOutputTrees),
2556  fTrackEfficiency(0),
2557  fRejectISR(kFALSE),
2558  fJetAreaType(fastjet::active_area),
2559  fJetGhostArea(0.005),
2560  fMCContainer(0),
2561  fAodEvent(0),
2562  fFastJetWrapper(0)
2563 {
2564  SetMakeGeneralHistograms(kTRUE);
2565  for (Int_t i = 0; i < nOutputTrees; i++){
2566  DefineOutput(2+i, TTree::Class());
2567  }
2568 }
2569 
2572 {
2573  if (fFastJetWrapper) delete fFastJetWrapper;
2574 }
2575 
2583 {
2584  AliRDHFCuts* analysiscuts = 0;
2585  TFile* filecuts = TFile::Open(cutfname);
2586  if (!filecuts || filecuts->IsZombie()) {
2587  ::Error("AliAnalysisTaskDmesonJets::LoadDMesonCutsFromFile", "Input file not found: will use std cuts.");
2588  filecuts = 0;
2589  }
2590 
2591  if (filecuts) analysiscuts = dynamic_cast<AliRDHFCuts*>(filecuts->Get(cutsname));
2592 
2593  if (!analysiscuts) {
2594  ::Error("AliAnalysisTaskDmesonJets::LoadDMesonCutsFromFile", "Could not find analysis cuts '%s' in '%s'.", cutsname.Data(), cutfname.Data());
2595  if (filecuts) {
2596  filecuts->ls();
2597  }
2598  }
2599  else {
2600  ::Info("AliAnalysisTaskDmesonJets::LoadDMesonCutsFromFile", "Cuts '%s' loaded from file '%s'", cutsname.Data(), cutfname.Data());
2601  }
2602 
2603  return analysiscuts;
2604 }
2605 
2618 {
2620  return AddAnalysisEngine(type, cutfname, cuttype, MCmode, jetDef, rhoName);
2621 }
2622 
2634 {
2635  AliRDHFCuts* cuts = 0;
2636 
2637  if (!cutfname.IsNull()) {
2638  TString cutsname;
2639 
2640  switch (type) {
2641  case kD0toKpi:
2642  case kD0toKpiLikeSign:
2643  cutsname = "D0toKpiCuts";
2644  break;
2645  case kDstartoKpipi:
2646  cutsname = "DStartoKpipiCuts";
2647  break;
2648  default:
2649  return 0;
2650  }
2651 
2652  if (!cuttype.IsNull()) {
2653  cutsname += TString::Format("_%s", cuttype.Data());
2654  }
2655 
2656  cuts = LoadDMesonCutsFromFile(cutfname, cutsname);
2657  if (cuts) cuts->PrintAll();
2658  }
2659 
2660  AnalysisEngine eng(type, MCmode, cuts);
2661 
2662  std::list<AnalysisEngine>::iterator it = FindAnalysisEngine(eng);
2663 
2664  if (it == fAnalysisEngines.end() || *it != eng) { // No analysis engine was found, adding a new one
2665  eng.AddJetDefinition(jetDef);
2666  it = fAnalysisEngines.insert(it, eng);
2667  ::Info("AliAnalysisTaskDmesonJets::AddAnalysisEngine", "A new analysis engine '%s' has been added. The total number of analysis engines is %lu.", eng.GetName(), fAnalysisEngines.size());
2668  }
2669  else {
2670  AnalysisEngine* found_eng = &(*it);
2671  ::Info("AliAnalysisTaskDmesonJets::AddAnalysisEngine", "An analysis engine '%s' with %lu jet definitions has been found. The total number of analysis engines is %lu. A new jet definition '%s' is being added.", found_eng->GetName(), found_eng->fJetDefinitions.size(), fAnalysisEngines.size(), jetDef.GetName());
2672  found_eng->AddJetDefinition(jetDef);
2673 
2674  if (cuts) {
2675  if (found_eng->fRDHFCuts != 0) ::Warning("AliAnalysisTaskDmesonJets::AddAnalysisEngine", "D meson cuts were already defined for this D meson type. They will be overwritten.");
2676  found_eng->SetRDHFCuts(cuts);
2677  }
2678  }
2679 
2680  return &(*it);
2681 }
2682 
2683 std::list<AliAnalysisTaskDmesonJets::AnalysisEngine>::iterator AliAnalysisTaskDmesonJets::FindAnalysisEngine(const AliAnalysisTaskDmesonJets::AnalysisEngine& eng)
2684 {
2685  std::list<AnalysisEngine>::iterator it = fAnalysisEngines.begin();
2686  while (it != fAnalysisEngines.end() && (*it) != eng) it++;
2687  return it;
2688 }
2689 
2692 {
2693  ::Info("UserCreateOutputObjects", "CreateOutputObjects of task %s", GetName());
2694 
2696 
2697  // Define histograms
2698  // the TList fOutput is already defined in AliAnalysisTaskEmcalLight::UserCreateOutputObjects()
2699 
2700  TString hname;
2701  TString htitle;
2702  TH1* h = 0;
2703  Int_t treeSlot = 0;
2704 
2705  Int_t maxTracks = 6000;
2706  Double_t maxRho = 500;
2707  if (fForceBeamType == kpp) {
2708  maxRho = 50;
2709  maxTracks = 200;
2710  }
2711  else if (fForceBeamType == kpA) {
2712  maxRho = 200;
2713  maxTracks = 500;
2714  }
2715 
2716  hname = "fHistCharmPt";
2717  htitle = hname + ";#it{p}_{T,charm} (GeV/#it{c});counts";
2718  fHistManager.CreateTH1(hname, htitle, 500, 0, 1000);
2719 
2720  hname = "fHistCharmEta";
2721  htitle = hname + ";#eta_{charm};counts";
2722  fHistManager.CreateTH1(hname, htitle, 400, -10, 10);
2723 
2724  hname = "fHistCharmPhi";
2725  htitle = hname + ";#phi_{charm};counts";
2726  fHistManager.CreateTH1(hname, htitle, 125, 0, TMath::TwoPi());
2727 
2728  hname = "fHistCharmPt_Eta05";
2729  htitle = hname + ";#it{p}_{T,charm} (GeV/#it{c});counts";
2730  fHistManager.CreateTH1(hname, htitle, 500, 0, 1000);
2731 
2732  hname = "fHistBottomPt";
2733  htitle = hname + ";#it{p}_{T,bottom} (GeV/#it{c});counts";
2734  fHistManager.CreateTH1(hname, htitle, 500, 0, 1000);
2735 
2736  hname = "fHistBottomEta";
2737  htitle = hname + ";#eta_{bottom};counts";
2738  fHistManager.CreateTH1(hname, htitle, 400, -10, 10);
2739 
2740  hname = "fHistBottomPhi";
2741  htitle = hname + ";#phi_{bottom};counts";
2742  fHistManager.CreateTH1(hname, htitle, 125, 0, TMath::TwoPi());
2743 
2744  hname = "fHistBottomPt_Eta05";
2745  htitle = hname + ";#it{p}_{T,bottom} (GeV/#it{c});counts";
2746  fHistManager.CreateTH1(hname, htitle, 500, 0, 1000);
2747 
2748  hname = "fHistHighestPartonPt";
2749  htitle = hname + ";#it{p}_{T,bottom} (GeV/#it{c});counts";
2750  fHistManager.CreateTH1(hname, htitle, 500, 0, 1000);
2751 
2752  hname = "fHistHighestPartonType";
2753  htitle = hname + ";type;counts";
2754  fHistManager.CreateTH1(hname, htitle, 10, 0, 10);
2755 
2756  hname = "fHistNHeavyQuarks";
2757  htitle = hname + ";number of heavy-quarks;counts";
2758  fHistManager.CreateTH1(hname, htitle, 21, -0.5, 20.5);
2759 
2760  ::Info("AliAnalysisTaskDmesonJets::UserCreateOutputObjects", "Allocating histograms for task '%s' (%lu analysis engines)", GetName(), fAnalysisEngines.size());
2761  for (auto &param : fAnalysisEngines) {
2762  ::Info("AliAnalysisTaskDmesonJets::UserCreateOutputObjects", "Allocating histograms for analysis engine '%s' (%lu jet definitions)", param.GetName(), param.fJetDefinitions.size());
2763 
2764  param.fHistManager = &fHistManager;
2765 
2766  hname = TString::Format("%s/fHistNAcceptedDmesonsVsNtracks", param.GetName());
2767  htitle = hname + ";#it{N}_{tracks};#it{N}_{D};events";
2768  h = fHistManager.CreateTH2(hname, htitle, 251, -0.5, 250.5, 21, -0.5, 20.5);
2769 
2770  hname = TString::Format("%s/fHistNTotAcceptedDmesons", param.GetName());
2771  htitle = hname + ";;#it{N}_{D}";
2772  h = fHistManager.CreateTH1(hname, htitle, 3, 0, 3);
2773 
2774  hname = TString::Format("%s/fHistNDmesons", param.GetName());
2775  htitle = hname + ";#it{N}_{D};events";
2776  h = fHistManager.CreateTH1(hname, htitle, 501, -0.5, 500.5);
2777 
2778  hname = TString::Format("%s/fHistNEvents", param.GetName());
2779  htitle = hname + ";Event status;counts";
2780  h = fHistManager.CreateTH1(hname, htitle, 2, 0, 2);
2781  h->GetXaxis()->SetBinLabel(1, "Accepted");
2782  h->GetXaxis()->SetBinLabel(2, "Rejected");
2783 
2784  hname = TString::Format("%s/fHistEventRejectionReasons", param.GetName());
2785  htitle = hname + ";Rejection reason;counts";
2786  h = fHistManager.CreateTH1(hname, htitle, 32, 0, 32);
2787 
2788  hname = TString::Format("%s/fHistRejectedDMesonPt", param.GetName());
2789  htitle = hname + ";#it{p}_{T,D} (GeV/#it{c});counts";
2790  fHistManager.CreateTH1(hname, htitle, 150, 0, 150);
2791 
2792  hname = TString::Format("%s/fHistRejectedDMesonEta", param.GetName());
2793  htitle = hname + ";#it{#eta}_{D};counts";
2794  fHistManager.CreateTH1(hname, htitle, 100, -2, 2);
2795 
2796  hname = TString::Format("%s/fHistRejectedDMesonPhi", param.GetName());
2797  htitle = hname + ";#it{#phi}_{D};counts";
2798  fHistManager.CreateTH1(hname, htitle, 200, 0, TMath::TwoPi());
2799 
2800  if (param.fMCMode != kMCTruth) {
2801  if (param.fCandidateType == kD0toKpi || param.fCandidateType == kD0toKpiLikeSign) {
2802  hname = TString::Format("%s/fHistRejectedDMesonInvMass", param.GetName());
2803  htitle = hname + ";#it{M}_{K#pi} (GeV/#it{c}^{2});counts";
2804  fHistManager.CreateTH1(hname, htitle, param.fNMassBins, param.fMinMass, param.fMaxMass);
2805  }
2806  else if (param.fCandidateType == kDstartoKpipi) {
2807  Double_t min = 0;
2808  Double_t max = 0;
2809 
2810  hname = TString::Format("%s/fHistRejectedDMeson2ProngInvMass", param.GetName());
2811  htitle = hname + ";#it{M}_{K#pi} (GeV/#it{c}^{2});counts";
2812  CalculateMassLimits(param.fMaxMass - param.fMinMass, 421, param.fNMassBins, min, max);
2813  fHistManager.CreateTH1(hname, htitle, param.fNMassBins, min, max);
2814 
2815  Double_t D0mass = TDatabasePDG::Instance()->GetParticle(421)->Mass();
2816  hname = TString::Format("%s/fHistRejectedDMesonDeltaInvMass", param.GetName());
2817  htitle = hname + ";#it{M}_{K#pi#pi} - #it{M}_{K#pi} (GeV/#it{c}^{2});counts";
2818  CalculateMassLimits(0.20, 413, param.fNMassBins*6, min, max);
2819  fHistManager.CreateTH1(hname, htitle, param.fNMassBins*6, min-D0mass, max-D0mass);
2820  }
2821  }
2822 
2823  if (param.fMCMode == kMCTruth) {
2824  hname = TString::Format("%s/fHistPartonPt", param.GetName());
2825  htitle = hname + ";#it{p}_{T,parton} (GeV/#it{c});counts";
2826  fHistManager.CreateTH1(hname, htitle, 500, 0, 1000);
2827 
2828  hname = TString::Format("%s/fHistPartonEta", param.GetName());
2829  htitle = hname + ";#eta_{parton};counts";
2830  fHistManager.CreateTH1(hname, htitle, 400, -10, 10);
2831 
2832  hname = TString::Format("%s/fHistPartonPhi", param.GetName());
2833  htitle = hname + ";#phi_{parton};counts";
2834  fHistManager.CreateTH1(hname, htitle, 125, 0, TMath::TwoPi());
2835 
2836  hname = TString::Format("%s/fHistPartonType", param.GetName());
2837  htitle = hname + ";type;counts";
2838  fHistManager.CreateTH1(hname, htitle, 10, 0, 10);
2839 
2840  hname = TString::Format("%s/fHistPrompt", param.GetName());
2841  htitle = hname + ";Type;counts";
2842  h = fHistManager.CreateTH1(hname, htitle, 3, 0, 3);
2843  h->GetXaxis()->SetBinLabel(1, "Unknown");
2844  h->GetXaxis()->SetBinLabel(2, "Prompt");
2845  h->GetXaxis()->SetBinLabel(3, "Non-Prompt");
2846 
2847  hname = TString::Format("%s/fHistAncestor", param.GetName());
2848  htitle = hname + ";Ancestor;counts";
2849  h = fHistManager.CreateTH1(hname, htitle, 4, 0, 4);
2850  h->GetXaxis()->SetBinLabel(1, "Unknown");
2851  h->GetXaxis()->SetBinLabel(2, "Charm");
2852  h->GetXaxis()->SetBinLabel(3, "Bottom");
2853  h->GetXaxis()->SetBinLabel(4, "Proton");
2854  }
2855 
2856  for (auto& jetDef : param.fJetDefinitions) {
2857  ::Info("AliAnalysisTaskDmesonJets::UserCreateOutputObjects", "Allocating histograms for jet definition '%s'", jetDef.GetName());
2858 
2859  if (param.fMCMode == kMCTruth) {
2860  hname = TString::Format("%s/%s/fHistNDmesonsVsNconstituents", param.GetName(), jetDef.GetName());
2861  htitle = hname + ";#it{N}_{constituents};#it{N}_{D};counts";
2862  h = fHistManager.CreateTH2(hname, htitle, 51, -0.5, 50.5, 10, 0.5, 10.5);
2863  }
2864 
2865  hname = TString::Format("%s/%s/fHistMCParticleRejectionReason", param.GetName(), jetDef.GetName());
2866  htitle = hname + ";Track rejection reason;#it{p}_{T,track} (GeV/#it{c});counts";
2867  h = fHistManager.CreateTH2(hname, htitle, 32, 0, 32, 150, 0, 150);
2868  SetRejectionReasonLabels(h->GetXaxis());
2869 
2870  hname = TString::Format("%s/%s/fHistTrackRejectionReason", param.GetName(), jetDef.GetName());
2871  htitle = hname + ";Track rejection reason;#it{p}_{T,track} (GeV/#it{c});counts";
2872  h = fHistManager.CreateTH2(hname, htitle, 32, 0, 32, 150, 0, 150);
2873  SetRejectionReasonLabels(h->GetXaxis());
2874 
2875  hname = TString::Format("%s/%s/fHistClusterRejectionReason", param.GetName(), jetDef.GetName());
2876  htitle = hname + ";Cluster rejection reason;#it{p}_{T,cluster} (GeV/#it{c});counts";
2877  h = fHistManager.CreateTH2(hname, htitle, 32, 0, 32, 150, 0, 150);
2878  SetRejectionReasonLabels(h->GetXaxis());
2879 
2880  hname = TString::Format("%s/%s/fHistDMesonDaughterNotInJet", param.GetName(), jetDef.GetName());
2881  htitle = hname + ";#it{p}_{T,track} (GeV/#it{c});counts";
2882  fHistManager.CreateTH1(hname, htitle, 200, 0, 100);
2883 
2884  hname = TString::Format("%s/%s/fHistRejectedJetPt", param.GetName(), jetDef.GetName());
2885  htitle = hname + ";#it{p}_{T,jet} (GeV/#it{c});counts";
2886  fHistManager.CreateTH1(hname, htitle, 150, 0, 150);
2887 
2888  hname = TString::Format("%s/%s/fHistRejectedJetEta", param.GetName(), jetDef.GetName());
2889  htitle = hname + ";#it{#eta}_{jet};counts";
2890  fHistManager.CreateTH1(hname, htitle, 100, -2, 2);
2891 
2892  hname = TString::Format("%s/%s/fHistRejectedJetPhi", param.GetName(), jetDef.GetName());
2893  htitle = hname + ";#it{#phi}_{jet};counts";
2894  fHistManager.CreateTH1(hname, htitle, 200, 0, TMath::TwoPi());
2895 
2896  if (!jetDef.fRhoName.IsNull()) {
2897  hname = TString::Format("%s/%s/fHistRhoVsLeadJetPt", param.GetName(), jetDef.GetName());
2898  htitle = hname + ";#it{p}_{T,jet} (GeV/#it{c});#rho (GeV/#it{c} #times rad^{-1});counts";
2899  fHistManager.CreateTH2(hname, htitle, 300, 0, 150, 1000, 0, maxRho);
2900 
2901  hname = TString::Format("%s/%s/fHistRhoVsLeadDPt", param.GetName(), jetDef.GetName());
2902  htitle = hname + ";#it{p}_{T,D} (GeV/#it{c});#rho (GeV/#it{c} #times rad^{-1});counts";
2903  fHistManager.CreateTH2(hname, htitle, 300, 0, 150, 1000, 0, maxRho);
2904 
2905  hname = TString::Format("%s/%s/fHistRhoVsCent", param.GetName(), jetDef.GetName());
2906  htitle = hname + ";Centrality (%);#rho (GeV/#it{c} #times rad^{-1});counts";
2907  fHistManager.CreateTH2(hname, htitle, 100, 0, 100, 1000, 0, maxRho);
2908 
2909  hname = TString::Format("%s/%s/fHistLeadJetPtVsCent", param.GetName(), jetDef.GetName());
2910  htitle = hname + ";Centrality (%);#it{p}_{T,jet} (GeV/#it{c});counts";
2911  fHistManager.CreateTH2(hname, htitle, 100, 0, 100, 300, 0, 150);
2912 
2913  hname = TString::Format("%s/%s/fHistLeadDPtVsCent", param.GetName(), jetDef.GetName());
2914  htitle = hname + ";Centrality (%);#it{p}_{T,D} (GeV/#it{c});counts";
2915  fHistManager.CreateTH2(hname, htitle, 100, 0, 100, 300, 0, 150);
2916 
2917  hname = TString::Format("%s/%s/fHistRhoVsNTracks", param.GetName(), jetDef.GetName());
2918  htitle = hname + ";no. of tracks;#rho (GeV/#it{c} #times rad^{-1});counts";
2919  fHistManager.CreateTH2(hname, htitle, 200, 0, maxTracks, 1000, 0, maxRho);
2920 
2921  hname = TString::Format("%s/%s/fHistLeadJetPtVsNTracks", param.GetName(), jetDef.GetName());
2922  htitle = hname + ";no. of tracks;#it{p}_{T,jet} (GeV/#it{c});counts";
2923  fHistManager.CreateTH2(hname, htitle, 200, 0, maxTracks, 300, 0, 150);
2924 
2925  hname = TString::Format("%s/%s/fHistLeadDPtVsNTracks", param.GetName(), jetDef.GetName());
2926  htitle = hname + ";no. of tracks;#it{p}_{T,D} (GeV/#it{c});counts";
2927  fHistManager.CreateTH2(hname, htitle, 200, 0, maxTracks, 300, 0, 150);
2928  }
2929  }
2930  switch (fOutputType) {
2931  case kTreeOutput:
2932  param.BuildTree(GetName());
2933  if (treeSlot < fNOutputTrees) {
2934  param.AssignDataSlot(treeSlot+2);
2935  treeSlot++;
2937  }
2938  else {
2939  AliError(Form("Number of data output slots %d not sufficient. Tree of analysis engine %s will not be posted!", fNOutputTrees, param.GetName()));
2940  }
2941  break;
2942  case kTHnOutput:
2943  param.BuildHnSparse(fEnabledAxis);
2944  break;
2945  case kNoOutput:
2946  break;
2947  }
2948  }
2949 
2951 
2952  PostData(1, fOutput);
2953 }
2954 
2958 {
2960 
2961  // Load the event
2962  fAodEvent = dynamic_cast<AliAODEvent*>(fInputEvent);
2963 
2964  fFastJetWrapper = new AliFJWrapper(fName, fTitle);
2965 
2966  fFastJetWrapper->SetAreaType((fastjet::AreaType)fJetAreaType);
2968 
2969  if (!fAodEvent) {
2970  AliError(Form("This task need an AOD event (Task '%s'). Expect troubles...", GetName()));
2971  //return;
2972  }
2973 
2974  TRandom* rnd = 0;
2975  if (fTrackEfficiency > 0 && fTrackEfficiency < 1) rnd = new TRandom3(0);
2976 
2977  for (auto cont_it : fParticleCollArray) {
2978  AliHFAODMCParticleContainer* part_cont = dynamic_cast<AliHFAODMCParticleContainer*>(cont_it.second);
2979  if (part_cont) fMCContainer = part_cont;
2980  }
2981 
2982  for (auto &params : fAnalysisEngines) {
2983 
2984  params.fAodEvent = fAodEvent;
2985  params.fFastJetWrapper = fFastJetWrapper;
2986  params.fTrackEfficiency = fTrackEfficiency;
2987  params.fRejectISR = fRejectISR;
2988  params.fRandomGen = rnd;
2989 
2990  for (auto &jetdef: params.fJetDefinitions) {
2991  if (!jetdef.fRhoName.IsNull()) {
2992  jetdef.fRho = dynamic_cast<AliRhoParameter*>(fInputEvent->FindListObject(jetdef.fRhoName));
2993  if (!jetdef.fRho) {
2994  ::Error("AliAnalysisTaskDmesonJets::ExecOnce",
2995  "%s: Could not find rho object '%s' for engine '%s'",
2996  GetName(), jetdef.fRhoName.Data(), params.GetName());
2997  }
2998  }
2999  }
3000 
3001  if (!params.fRDHFCuts) {
3002  if (params.fMCMode == kMCTruth) {
3003  ::Warning("AliAnalysisTaskDmesonJets::ExecOnce",
3004  "%s: RDHF cuts not provided for engine '%s'.",
3005  GetName(), params.GetName());
3006  }
3007  else {
3008  ::Error("AliAnalysisTaskDmesonJets::ExecOnce",
3009  "%s: RDHF cuts not provided. Engine '%s' disabled.",
3010  GetName(), params.GetName());
3011  params.fInhibit = kTRUE;
3012  }
3013  }
3014 
3015  params.fMCContainer = fMCContainer;
3016 
3017  for (auto cont_it : fParticleCollArray) {
3018  AliTrackContainer* track_cont = dynamic_cast<AliTrackContainer*>(cont_it.second);
3019  if (track_cont) params.fTrackContainers.push_back(track_cont);
3020  }
3021 
3022  for (auto cont_it : fClusterCollArray) params.fClusterContainers.push_back(cont_it.second);
3023 
3024  if (fAodEvent) params.Init(fGeom, fAodEvent->GetRunNumber());
3025 
3026  if (params.fMCMode != kMCTruth && fAodEvent) {
3027  params.fCandidateArray = dynamic_cast<TClonesArray*>(fAodEvent->GetList()->FindObject(params.fBranchName.Data()));
3028 
3029  if (params.fCandidateArray) {
3030  TString className;
3031  if (params.fCandidateType == kD0toKpi || params.fCandidateType == kD0toKpiLikeSign) {
3032  className = "AliAODRecoDecayHF2Prong";
3033  }
3034  else if (params.fCandidateType == kDstartoKpipi) {
3035  className = "AliAODRecoCascadeHF";
3036  }
3037  if (!params.fCandidateArray->GetClass()->InheritsFrom(className)) {
3038  ::Error("AliAnalysisTaskDmesonJets::ExecOnce",
3039  "%s: Objects of type %s in %s are not inherited from %s! Task will be disabled!",
3040  GetName(), params.fCandidateArray->GetClass()->GetName(), params.fCandidateArray->GetName(), className.Data());
3041  params.fCandidateArray = 0;
3042  params.fInhibit = kTRUE;
3043  }
3044  }
3045  else {
3046  ::Error("AliAnalysisTaskDmesonJets::ExecOnce",
3047  "Could not find candidate array '%s', skipping the event. Analysis engine '%s' will be disabled!",
3048  params.fBranchName.Data(), params.GetName());
3049  params.fInhibit = kTRUE;
3050  }
3051  }
3052 
3053  if (params.fMCMode != kNoMC) {
3054  if (!params.fMCContainer) {
3055  ::Error("AliAnalysisTaskDmesonJets::ExecOnce",
3056  "No MC particle container was provided. Analysis engine '%s' will be disabled!",
3057  params.GetName());
3058  params.fInhibit = kTRUE;
3059  }
3060  }
3061 
3062  if (params.fMCMode != kMCTruth) {
3063  if (params.fTrackContainers.size() == 0 && params.fClusterContainers.size() == 0) {
3064  ::Error("AliAnalysisTaskDmesonJets::ExecOnce",
3065  "No track container and no cluster container were provided. Analysis engine '%s' will be disabled!",
3066  params.GetName());
3067  params.fInhibit = kTRUE;
3068  }
3069  }
3070  }
3071 }
3072 
3077 {
3078  TString hname;
3079 
3080  // Fix for temporary bug in ESDfilter
3081  // The AODs with null vertex pointer didn't pass the PhysSel
3082  // Now adding an entry in the histogram so as to check that this is actually cutting anything out
3083  if (fAodEvent && (!fAodEvent->GetPrimaryVertex() || TMath::Abs(fAodEvent->GetMagneticField()) < 0.001)) {
3084  for (auto &eng : fAnalysisEngines) {
3085  if (eng.fInhibit) continue;
3086  hname = TString::Format("%s/fHistEventRejectionReasons", eng.GetName());
3087  fHistManager.FillTH1(hname, "ESDfilterBug");
3088  }
3089  return kFALSE;
3090  }
3091 
3092  if (fAodEvent) {
3093  Int_t matchingAODdeltaAODlevel = AliRDHFCuts::CheckMatchingAODdeltaAODevents();
3094  if (matchingAODdeltaAODlevel <= 0) {
3095  // AOD/deltaAOD trees have different number of entries || TProcessID do not match while it was required
3096  for (auto &eng : fAnalysisEngines) {
3097  if (eng.fInhibit) continue;
3098  hname = TString::Format("%s/fHistEventRejectionReasons", eng.GetName());
3099  fHistManager.FillTH1(hname, "MismatchDeltaAOD");
3100  }
3101  return kFALSE;
3102  }
3103  }
3104 
3105  for (auto &eng : fAnalysisEngines) {
3106  eng.fDmesonJets.clear();
3107  if (eng.fInhibit) continue;
3108 
3109  eng.fCent = fCent;
3110 
3111  //Event selection
3112  hname = TString::Format("%s/fHistNEvents", eng.GetName());
3113  if (fAodEvent) {
3114  Bool_t iseventselected = kTRUE;
3115  if (eng.fRDHFCuts) iseventselected = eng.fRDHFCuts->IsEventSelected(fAodEvent);
3116  if (!iseventselected) {
3117  fHistManager.FillTH1(hname, "Rejected");
3118  hname = TString::Format("%s/fHistEventRejectionReasons", eng.GetName());
3119  UInt_t bitmap = eng.fRDHFCuts->GetEventRejectionBitMap();
3120  TString label;
3121  do {
3122  label = GetHFEventRejectionReasonLabel(bitmap);
3123  if (label.IsNull()) break;
3124  fHistManager.FillTH1(hname, label);
3125  } while (true);
3126 
3127  continue;
3128  }
3129  }
3130 
3131  fHistManager.FillTH1(hname, "Accepted");
3132 
3133  AliDebug(2, "Event selected");
3134 
3135  eng.RunAnalysis();
3136  }
3137  return kTRUE;
3138 }
3139 
3144 {
3145  for (auto &param : fAnalysisEngines) {
3146  if (param.fInhibit) continue;
3147 
3148  if (fOutputType == kTreeOutput) {
3149  param.FillTree(fApplyKinematicCuts);
3151  }
3152  else if (fOutputType == kTHnOutput) {
3153  param.FillHnSparse(fApplyKinematicCuts);
3154  }
3155  }
3157  return kTRUE;
3158 }
3159 
3162 {
3163  auto itcont = fMCContainer->all_momentum();
3164  Int_t nHQ = 0;
3165  Double_t highestPartonPt = 0;
3166  Int_t absPdgHighParton = 0;
3167  for (auto part : itcont) {
3168  Int_t absPdgCode = TMath::Abs(part.second->GetPdgCode());
3169 
3170  // Skip all particles that are not either quarks or gluons
3171  if (absPdgCode > 9 && absPdgCode != 21) continue;
3172 
3173  // Look for highest momentum parton
3174  if (highestPartonPt < part.first.Pt()) {
3175  highestPartonPt = part.first.Pt();
3176  absPdgHighParton = absPdgCode;
3177  }
3178  /*
3179  // Look for the mother PDG code
3180  Int_t motherIndex = part.second->GetMother();
3181  AliAODMCParticle *mother = 0;
3182  Int_t motherPdg = 0;
3183  Double_t motherPt = 0;
3184  if (motherIndex >= 0) {
3185  mother = fMCContainer->GetMCParticle(motherIndex);
3186  if (motherIndex) {
3187  motherPdg = TMath::Abs(mother->GetPdgCode());
3188  motherPt = mother->Pt();
3189  }
3190  }
3191  */
3192  if (absPdgCode != 4 && absPdgCode != 5) continue;
3193  Bool_t notLastInPartonShower = kFALSE;
3194  for (Int_t idaugh = 0; idaugh < 2; idaugh++){
3195  Int_t daughterIndex = part.second->GetDaughter(idaugh);
3196  if (daughterIndex < 0) {
3197  AliDebug(10, Form("Could not find daughter of heavy quark (pdg=%d, pt=%.3f)!", absPdgCode, part.first.Pt()));
3198  continue;
3199  }
3200  AliAODMCParticle *daughter = fMCContainer->GetMCParticle(daughterIndex);
3201  if (!daughter) {
3202  AliDebug(10, Form("Could not find daughter %d of heavy quark (pdg=%d, pt=%.3f)!", daughterIndex, absPdgCode, part.first.Pt()));
3203  continue;
3204  }
3205  Int_t daughterAbsPdgCode = TMath::Abs(daughter->GetPdgCode());
3206  if (daughterAbsPdgCode <= 9 || daughterAbsPdgCode == 21) notLastInPartonShower = kTRUE; // this parton is not the last parton in the shower
3207  AliDebug(10, Form("Found daughter with PDG=%d, pt=%.3f", daughterAbsPdgCode, daughter->Pt()));
3208  }
3209  if (notLastInPartonShower) continue;
3210 
3211  if (absPdgCode == 4) {
3212  fHistManager.FillTH1("fHistCharmPt", part.first.Pt());
3213  fHistManager.FillTH1("fHistCharmEta", part.first.Eta());
3214  fHistManager.FillTH1("fHistCharmPhi", part.first.Phi_0_2pi());
3215  if (TMath::Abs(part.first.Eta()) < 0.5) fHistManager.FillTH1("fHistCharmPt_Eta05", part.first.Pt());
3216  }
3217  else if (absPdgCode == 5) {
3218  fHistManager.FillTH1("fHistBottomPt", part.first.Pt());
3219  fHistManager.FillTH1("fHistBottomEta", part.first.Eta());
3220  fHistManager.FillTH1("fHistBottomPhi", part.first.Phi_0_2pi());
3221  if (TMath::Abs(part.first.Eta()) < 0.5) fHistManager.FillTH1("fHistBottomPt_Eta05", part.first.Pt());
3222  }
3223  nHQ++;
3224  }
3225  fHistManager.FillTH1("fHistNHeavyQuarks", nHQ);
3226  fHistManager.FillTH1("fHistHighestPartonPt",highestPartonPt);
3227  Int_t partonType = 0;
3228  if (absPdgHighParton == 9 || absPdgHighParton == 21) {
3229  partonType = 7;
3230  }
3231  else {
3232  partonType = absPdgHighParton;
3233  }
3234  fHistManager.FillTH1("fHistHighestPartonType",partonType);
3235 }
3236 
3245 {
3246  TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(TMath::Abs(pdg));
3247 
3248  Double_t mass = part->Mass();
3249 
3250  // To make sure that the PDG mass value is not at the edge of a bin
3251  if (nbins % 2 == 0) {
3252  minMass = mass - range / 2 - range / nbins / 2;
3253  maxMass = mass + range / 2 - range / nbins / 2;
3254  }
3255  else {
3256  minMass = mass - range / 2;
3257  maxMass = mass + range / 2;
3258  }
3259 }
3260 
3267 {
3268  static TString label;
3269  label = "";
3270 
3271  if (bitmap & BIT(AliRDHFCuts::kNotSelTrigger)) {
3272  label = "NotSelTrigger";
3273  bitmap &= ~BIT(AliRDHFCuts::kNotSelTrigger);
3274  return label.Data();
3275  }
3276  if (bitmap & BIT(AliRDHFCuts::kNoVertex)) {
3277  label = "NoVertex";
3278  bitmap &= ~BIT(AliRDHFCuts::kNoVertex);
3279  return label.Data();
3280  }
3281  if (bitmap & BIT(AliRDHFCuts::kTooFewVtxContrib)) {
3282  label = "TooFewVtxContrib";
3283  bitmap &= ~BIT(AliRDHFCuts::kTooFewVtxContrib);
3284  return label.Data();
3285  }
3286  if (bitmap & BIT(AliRDHFCuts::kZVtxOutFid)) {
3287  label = "ZVtxOutFid";
3288  bitmap &= ~BIT(AliRDHFCuts::kZVtxOutFid);
3289  return label.Data();
3290  }
3291  if (bitmap & BIT(AliRDHFCuts::kPileup)) {
3292  label = "Pileup";
3293  bitmap &= ~BIT(AliRDHFCuts::kPileup);
3294  return label.Data();
3295  }
3296  if (bitmap & BIT(AliRDHFCuts::kOutsideCentrality)) {
3297  label = "OutsideCentrality";
3298  bitmap &= ~BIT(AliRDHFCuts::kOutsideCentrality);
3299  return label.Data();
3300  }
3301  if (bitmap & BIT(AliRDHFCuts::kPhysicsSelection)) {
3302  label = "PhysicsSelection";
3303  bitmap &= ~BIT(AliRDHFCuts::kPhysicsSelection);
3304  return label.Data();
3305  }
3306  if (bitmap & BIT(AliRDHFCuts::kBadSPDVertex)) {
3307  label = "BadSPDVertex";
3308  bitmap &= ~BIT(AliRDHFCuts::kBadSPDVertex);
3309  return label.Data();
3310  }
3311  if (bitmap & BIT(AliRDHFCuts::kZVtxSPDOutFid)) {
3312  label = "ZVtxSPDOutFid";
3313  bitmap &= ~BIT(AliRDHFCuts::kZVtxSPDOutFid);
3314  return label.Data();
3315  }
3316  if (bitmap & BIT(AliRDHFCuts::kCentralityFlattening)) {
3317  label = "CentralityFlattening";
3318  bitmap &= ~BIT(AliRDHFCuts::kCentralityFlattening);
3319  return label.Data();
3320  }
3321  if (bitmap & BIT(AliRDHFCuts::kBadTrackV0Correl)) {
3322  label = "BadTrackV0Correl";
3323  bitmap &= ~BIT(AliRDHFCuts::kBadTrackV0Correl);
3324  return label.Data();
3325  }
3326 
3327  return label.Data();
3328 }
3329 
3336 {
3337  if (eng.GetDataSlotNumber() >= 0 && eng.GetTree()) {
3338  PostData(eng.GetDataSlotNumber(), eng.GetTree());
3339  return eng.GetDataSlotNumber();
3340  }
3341  else {
3342  return -1;
3343  }
3344 }
3345 
3355 {
3356  // Get the pointer to the existing analysis manager via the static access method
3357  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3358  if (!mgr) {
3359  ::Error("AddTaskDmesonJets", "No analysis manager to connect to.");
3360  return NULL;
3361  }
3362 
3363  // Check the analysis type using the event handlers connected to the analysis manager
3364  AliVEventHandler* handler = mgr->GetInputEventHandler();
3365  if (!handler) {
3366  ::Error("AddTaskEmcalJetSpectraQA", "This task requires an input event handler");
3367  return NULL;
3368  }
3369 
3370  EDataType_t dataType = kUnknownDataType;
3371 
3372  if (handler->InheritsFrom("AliESDInputHandler")) {
3373  dataType = kESD;
3374  }
3375  else if (handler->InheritsFrom("AliAODInputHandler")) {
3376  dataType = kAOD;
3377  }
3378 
3379  // Init the task and do settings
3380  if (ntracks == "usedefault") {
3381  if (dataType == kESD) {
3382  ntracks = "Tracks";
3383  }
3384  else if (dataType == kAOD) {
3385  ntracks = "tracks";
3386  }
3387  else {
3388  ntracks = "";
3389  }
3390  }
3391 
3392  if (nclusters == "usedefault") {
3393  if (dataType == kESD) {
3394  nclusters = "CaloClusters";
3395  }
3396  else if (dataType == kAOD) {
3397  nclusters = "caloClusters";
3398  }
3399  else {
3400  nclusters = "";
3401  }
3402  }
3403 
3404  if (nMCpart == "usedefault") {
3405  nMCpart = "mcparticles"; // Always needs AliAODMCParticle objects
3406  }
3407 
3408  TString name("AliAnalysisTaskDmesonJets");
3409  if (strcmp(suffix, "") != 0) {
3410  name += TString::Format("_%s", suffix.Data());
3411  }
3412 
3413  AliAnalysisTaskDmesonJets* jetTask = new AliAnalysisTaskDmesonJets(name, nMaxTrees);
3414 
3415  if (!ntracks.IsNull()) {
3416  AliHFTrackContainer* trackCont = new AliHFTrackContainer(ntracks);
3417  jetTask->AdoptParticleContainer(trackCont);
3418  }
3419 
3420  if (!nMCpart.IsNull()) {
3421  AliMCParticleContainer* partCont = new AliHFAODMCParticleContainer(nMCpart);
3422  partCont->SetEtaLimits(-1.5, 1.5);
3423  partCont->SetPtLimits(0, 1000);
3424  jetTask->AdoptParticleContainer(partCont);
3425  }
3426 
3427  jetTask->AddClusterContainer(nclusters.Data());
3428 
3429  // Final settings, pass to manager and set the containers
3430  mgr->AddTask(jetTask);
3431 
3432  // Create containers for input/output
3433  AliAnalysisDataContainer* cinput1 = mgr->GetCommonInputContainer();
3434  TString contname1(name);
3435  contname1 += "_histos";
3436  AliAnalysisDataContainer* coutput1 = mgr->CreateContainer(contname1.Data(),
3437  TList::Class(), AliAnalysisManager::kOutputContainer,
3438  Form("%s", AliAnalysisManager::GetCommonFileName()));
3439 
3440  mgr->ConnectInput(jetTask, 0, cinput1);
3441  mgr->ConnectOutput(jetTask, 1, coutput1);
3442 
3443  for (Int_t i = 0; i < nMaxTrees; i++) {
3444  TString contname = TString::Format("%s_tree_%d", name.Data(), i);
3445  AliAnalysisDataContainer *coutput = mgr->CreateContainer(contname.Data(),
3446  TTree::Class(),AliAnalysisManager::kOutputContainer,
3447  Form("%s", AliAnalysisManager::GetCommonFileName()));
3448  mgr->ConnectOutput(jetTask, 2+i, coutput);
3449  }
3450  return jetTask;
3451 }
Double32_t fCorrZ
Z of the D meson after subtracting average background.
Lightweight class that encapsulates D meson jets.
Int_t pdg
void Print() const
Prints the content of this object in the standard output.
AliDmesonInfoSummary * fCurrentDmesonJetInfo
! Current D meson jet info
AliAODMCParticle * fParton
! pointer to the parton in the shower tree of the D meson (only for particle level D mesons) ...
std::list< AnalysisEngine > fAnalysisEngines
Array of analysis parameters.
std::string fClassName
Class name where the event was not found.
AliEMCALGeometry * fGeom
!emcal geometry
void SetDMesonCandidate(AliAODRecoDecay *c)
Analysis task for D meson jets.
UInt_t fRejectedOrigin
Bit mask with D meson origins that are rejected (used for MC analysis, i.e. signal-only, background-only and particle-level)
virtual void Set(const AliDmesonJetInfo &source)
Invariant mass of the D0 meson candidate in GeV/c2.
virtual Int_t Run()
double Double_t
Definition: External.C:58
Bool_t IsJetInAcceptance(const AliJetInfo &jet) const
Double_t fSoftPionPt
! Transverse momentum of the soft pion of the D* candidate
EDataType_t
Switch for the data type.
virtual AliAODMCParticle * GetMCParticle(Int_t i=-1) const
void Getd0MeasMinusExpProng(Int_t ip, Double_t magf, Double_t &d0diff, Double_t &errd0diff) const
const char * title
Definition: MakeQAPdf.C:27
AliRDHFCuts * fRDHFCuts
D meson candidates cuts.
virtual void Set(const AliDmesonJetInfo &source)
TString fRhoName
Name of the object that holds the average background value.
Lightweight class that encapsulates D meson jets.
std::vector< AliTrackContainer * > fTrackContainers
! Track containers
AnalysisEngine * AddAnalysisEngine(ECandidateType_t type, TString cutfname, TString cuttype, EMCMode_t bkgMode, EJetType_t jettype, Double_t jetradius, TString rhoName="")
Double_t fTrackEfficiency
Artificial tracking inefficiency (0...1)
std::vector< AliClusterContainer * > fClusterContainers
! Cluster containers
Int_t MatchToMC(Int_t pdgabs, Int_t pdgabs2prong, Int_t *pdgDg, Int_t *pdgDg2prong, TClonesArray *mcArray, Bool_t isV0=kFALSE) const
AliHFAODMCParticleContainer * fMCContainer
! MC particle container
ERecoScheme_t fRecoScheme
Jet recombination scheme (pt scheme, E scheme, ...)
const TObjArray & GetDaughterList() const
Double_t fMaxNeutralPt
Transverse momentum of the leading neutral particle (or cluster)
void RunDetectorLevelAnalysis()
Run a detector level analysis.
Double_t mass
Container with name, TClonesArray and cuts for particles.
Double32_t fPartonPt
Transverse momentum of the parton.
friend bool operator<(const AnalysisEngine &lhs, const AnalysisEngine &rhs)
void FillTH2(const char *hname, double x, double y, double weight=1., Option_t *opt="")
Fill a 2D histogram within the container.
virtual void UserCreateOutputObjects()
Creates the output containers.
void FillPartonLevelHistograms()
Fill histograms with parton-level information.
static Int_t CheckMatchingAODdeltaAODevents()
Double32_t fInvMass
Invariant mass of the D0 meson candidate in GeV/c2.
Lightweight class that encapsulates D meson jets.
Double_t fInvMass2Prong
! 2-prong mass of the D* candidate (w/o the soft pion)
friend bool operator==(const AnalysisEngine &lhs, const AnalysisEngine &rhs)
Double_t fMinChargedPt
Minimum pt of the leading charged particle (or track)
static void CalculateMassLimits(Double_t range, Int_t pdg, Int_t nbins, Double_t &minMass, Double_t &maxMass)
AliAODEvent * fAodEvent
! AOD event
Bool_t FindJet(AliAODRecoDecayHF2Prong *Dcand, AliDmesonJetInfo &DmesonJet, AliHFJetDefinition &jetDef)
UInt_t fEnabledAxis
Use bit defined in EAxis_t to enable axis in the THnSparse.
Double32_t fPtK
Transverse momentum of the kaon.
TRandom * fRandomGen
! Random number generator
Double32_t fCosPointing
Cosine of the pointing angle.
AliRhoParameter * fRho
Object that holds the average background value.
EMCMode_t fMCMode
MC mode: No MC (data and MC detector level), background-only (MC), signal-only (MC), MC truth (particle level)
Bool_t FillRecoCand(AliVEvent *event, AliAODRecoDecayHF3Prong *rd3)
Double_t fJetGhostArea
Area of the ghost particles.
void SetRecombScheme(const fastjet::RecombinationScheme &scheme)
Definition: AliFJWrapper.h:122
AnalysisEngine()
This is the default constructor, used for ROOT I/O purposes.
Int_t fDataSlotNumber
! Data slot where the tree output is posted
Double32_t fPtPi
Transverse momentum of the pion.
void Init(const AliEMCALGeometry *const geom, Int_t runNumber)
Initialize the analysis engine.
static FJRecoScheme ConvertToFJRecoScheme(ERecoScheme_t reco)
AliVParticle * fDmesonParticle
! pointer to the particle object
TString part
use mixed event to constrain combinatorial background
Definition: InvMassFit.C:52
static TString GenerateJetName(EJetType_t jetType, EJetAlgo_t jetAlgo, ERecoScheme_t recoScheme, Double_t radius, AliParticleContainer *partCont, AliClusterContainer *clusCont, TString tag)
static std::pair< AliAnalysisTaskDmesonJets::EMesonOrigin_t, AliAODMCParticle * > IsPromptCharm(const AliAODMCParticle *part, TClonesArray *mcArray)
virtual void Set(const AliDmesonJetInfo &source)
Double32_t fN
Number of jet constituents.
void SetR(Double_t r)
Definition: AliFJWrapper.h:127
Select tracks based on specific prescriptions of HF analysis.
Double32_t fPt
Transverse momentum of the jet in GeV/c.
ECandidateType_t fCandidateType
Candidate type.
Double_t GetDistance(std::string n, Double_t &deta, Double_t &dphi) const
Int_t fMCLabel
! MC label, i.e. index of the generator level D meson (only for detector level D meson candidates) ...
EBeamType_t fForceBeamType
forced beam type
const Int_t nPtBins
Double32_t fR
Distance between D meson and jet axis.
virtual void Set(const AliDmesonJetInfo &source)
void AddInputVectors(AliEmcalContainer *cont, Int_t offset, TH2 *rejectHist=0, Double_t eff=0.)
const std::vector< fastjet::PseudoJet > & GetInclusiveJets() const
Definition: AliFJWrapper.h:34
EJetType_t fJetType
Jet type (charged, full, neutral)
Double32_t fPt
Transverse momentum of the D meson in GeV/c.
TH2 * CreateTH2(const char *name, const char *title, int nbinsx, double xmin, double xmax, int nbinsy, double ymin, double ymax, Option_t *opt="")
Create a new TH2 within the container.
virtual void Set(const AliDmesonJetInfo &source)
AliTLorentzVector fD
! 4-momentum of the D meson candidate
Double_t GetDistance(const AliJetInfo &jet, Double_t &deta, Double_t &dphi) const
TObject * FindObject(const char *name) const
Find an object inside the container.
int Int_t
Definition: External.C:63
unsigned int UInt_t
Definition: External.C:33
THashList * GetListOfHistograms() const
Get the list of histograms.
Definition: THistManager.h:671
Double_t CosThetaStarD0bar() const
angle of K
AliAnalysisTaskDmesonJets()
This is the default constructor, used for ROOT I/O purposes.
virtual void Reset()
Reset the current object.
AnalysisEngine & operator=(const AnalysisEngine &source)
Lightweight class that encapsulates D meson jets for PbPb analysis.
Struct that encapsulates analysis parameters.
std::vector< AliHFJetDefinition >::iterator FindJetDefinition(const AliHFJetDefinition &eng)
Base task in the EMCAL framework (lighter version of AliAnalysisTaskEmcal)
Double_t Phi_0_2pi() const
static AliAODMCParticle * FindParticleOrigin(const AliAODMCParticle *part, TClonesArray *mcArray, EFindParticleOriginMode_t mode, const std::set< UInt_t > &pdgSet)
Double_t fMinNeutralPt
Minimum pt of the leading neutral particle (or cluster)
Bool_t fD0D0bar
! kTRUE if selected both as D0 and D0bar
void SetAlgorithm(const fastjet::JetAlgorithm &algor)
Definition: AliFJWrapper.h:121
TH1 * CreateTH1(const char *name, const char *title, int nbins, double xmin, double xmax, Option_t *opt="")
Create a new TH1 within the container.
AliAODTrack * GetBachelor() const
Bool_t fD0Extended
Store extended information in the tree (only for D0 mesons)
AliRDHFCuts * LoadDMesonCutsFromFile(TString cutfname, TString cutsname)
std::list< AnalysisEngine >::iterator FindAnalysisEngine(const AnalysisEngine &eng)
std::vector< AliHFJetDefinition > fJetDefinitions
Jet definitions.
Double_t fMaxNeutralPt
Maximum pt of the leading neutral particle (or cluster)
Double_t fMaxMass
Max mass in histogram axis.
EJetAlgo_t fJetAlgo
Jet algorithm (kt, anti-kt,...)
static const char * GetHFEventRejectionReasonLabel(UInt_t &bitmap)
Lightweight class that encapsulates D*.
virtual void Clear(const Option_t *="")
friend bool operator<(const AliHFJetDefinition &lhs, const AliHFJetDefinition &rhs)
Int_t mode
Definition: anaM.C:41
Bool_t ExtractDstarAttributes(const AliAODRecoCascadeHF *DstarCand, AliDmesonJetInfo &DmesonJet, UInt_t i)
void FillTH1(const char *hname, double x, double weight=1., Option_t *opt="")
Fill a 1D histogram within the container.
const AliJetInfo * GetJet(std::string n) const
Short_t fPartonType
! type of the parton in the shower tree (only for particle level D mesons)
TClonesArray * fCandidateArray
! D meson candidate array
const AliMCParticleIterableMomentumContainer all_momentum() const
virtual ~AliAnalysisTaskDmesonJets()
This is the standard destructor.
Byte_t fSelectionType
! for D0: 0=not selected, 1=D0, 2=D0bar
Bool_t ExtractD0Attributes(const AliAODRecoDecayHF2Prong *Dcand, AliDmesonJetInfo &DmesonJet, UInt_t i)
Select MC particles based on specific prescriptions of HF analysis.
static EMesonDecayChannel_t CheckDecayChannel(const AliAODMCParticle *part, TClonesArray *mcArray)
void SetGhostArea(Double_t gharea)
Definition: AliFJWrapper.h:125
AliDmesonJetInfo & operator=(const AliDmesonJetInfo &source)
Double_t fMaxChargedPt
Transverse momentum of the leading charged particle (or track)
Double32_t fCorrPt
Transverse momentum of the jet in GeV/c after subtracting average background.
std::vector< fastjet::PseudoJet > GetJetConstituents(UInt_t idx) const
friend bool operator==(const AliHFJetDefinition &lhs, const AliHFJetDefinition &rhs)
static FJJetAlgo ConvertToFJAlgo(EJetAlgo_t algo)
Double_t fMaxChargedPt
Maximum pt of the leading charged particle (or track)
decay
Definition: HFPtSpectrum.C:41
std::map< std::string, AliJetInfo > fJets
! list of jets
Look for the very first particle in the fragmentation tree.
AliAODMCParticle * fAncestor
! pointer to the ancestor particle in the shower tree of the D meson (only for particle level D meson...
Double32_t fDeltaInvMass
< Difference between the Kpipi and the Kpi invariant masses in GeV/c2
std::map< AliAODMCParticle *, Short_t > fPartons
! set of the partons in the shower that produced each D meson
Definition: External.C:220
Double_t minMass
Bool_t fRejectISR
! Reject initial state radiation
void RunParticleLevelAnalysis()
Run a particle level analysis.
std::map< std::string, AliParticleContainer * > fParticleCollArray
particle/track collection array
std::map< int, AliDmesonJetInfo > fDmesonJets
! Array containing the D meson jets
Double_t fTrackEfficiency
! Artificial tracking inefficiency (0...1) -> set automatically at ExecOnce by AliAnalysisTaskDmesonJ...
Bool_t fApplyKinematicCuts
Apply jet kinematic cuts.
Double32_t fSelectionType
Selection type: D0, D0bar, both.
Bool_t IsSelected(TObject *obj)
Definition: AliRDHFCuts.h:290
const char * GetName() const
Generate a name for this jet definition.
AliEventNotFound(const std::string &class_name, const std::string &method_name)
UInt_t fAcceptedDecay
Bit mask with D meson decays that are accepted (only used for particle-level analysis) ...
virtual void Set(const AliDmesonJetInfo &source, std::string n)
unsigned short UShort_t
Definition: External.C:28
Bool_t fReconstructed
! Whether this D meson was reconstructed (only for particle level D mesons)
Bool_t ExtractRecoDecayAttributes(const AliAODRecoDecayHF2Prong *Dcand, AliDmesonJetInfo &DmesonJet, UInt_t i)
Double_t InvMassD0() const
Bool_t fRejectISR
Reject initial state radiation.
EOutputType_t fOutputType
Output type: none, TTree or THnSparse.
virtual void AddInputVector(Double_t px, Double_t py, Double_t pz, Double_t E, Int_t index=-99999)
Double_t InvMassDstarKpipi() const
const AliVEvent * fEvent
! pointer to the ESD/AOD event
TArrayI fPDGdaughters
List of the PDG code of the daughters.
const Int_t nbins
Double_t maxMass
TString fBranchName
AOD branch where the D meson candidate are found.
bool Bool_t
Definition: External.C:53
Double_t CosPointingAngle() const
Int_t fNOutputTrees
Maximum number of output trees.
AliHFJetDefinition()
This is the default constructor, used for ROOT I/O purposes.
AliHFJetDefinition & operator=(const AliHFJetDefinition &source)
Int_t GetNAcceptedParticles() const
void SetAreaType(const fastjet::AreaType &atype)
Definition: AliFJWrapper.h:123
std::map< std::string, AliClusterContainer * > fClusterCollArray
cluster collection array
THnSparse * CreateTHnSparse(const char *name, const char *title, int ndim, const int *nbins, const double *min, const double *max, Option_t *opt="")
Create a new THnSparse within the container.
Double_t fCorrPt
Transverse momentum of the jet after subtracting the average background.
AliHFAODMCParticleContainer * fMCContainer
! MC particle container
AliJetInfoSummary ** fCurrentJetInfo
! Current jet info
virtual Bool_t IsInFiducialAcceptance(Double_t, Double_t) const
Definition: AliRDHFCuts.h:310
AliFJWrapper * fFastJetWrapper
! Fastjet wrapper
AliHFJetDefinition * AddJetDefinition(EJetType_t type, Double_t r, EJetAlgo_t algo, ERecoScheme_t reco)
Container for MC-true particles within the EMCAL framework.
Lightweight class that encapsulates D0.
Bool_t IsAnyJetInAcceptance(const AliDmesonJetInfo &dMesonJet) const
Double_t fCent
!event centrality
void SetCharge(EChargeCut_t c)
Container for jet within the EMCAL jet framework.
Definition: External.C:196
Int_t PostDataFromAnalysisEngine(const AnalysisEngine &eng)
AliFJWrapper * fFastJetWrapper
! Fastjet wrapper
THistManager fHistManager
Histogram manager.
void Reset()
Reset all fields to their default values.
static AliAnalysisTaskDmesonJets * AddTaskDmesonJets(TString ntracks="usedefault", TString nclusters="usedefault", TString nMCpart="", Int_t nMaxTrees=2, TString suffix="")
virtual void Set(const AliDmesonJetInfo &source, std::string n)
Double_t fMinMass
Min mass in histogram axis.