1 #ifndef TRUTHRIVETTOOLS_HIGGSTEMPLATECROSSSECTIONS_CC
2 #define TRUTHRIVETTOOLS_HIGGSTEMPLATECROSSSECTIONS_CC
5 #include "Rivet/Analysis.hh"
6 #include "Rivet/Particle.hh"
7 #include "Rivet/Projections/FastJets.hh"
34 if (ptcl.genParticle()->end_vertex()) {
35 if (!
hasChild(ptcl.genParticle(), ptcl.pid()))
45 const ConstGenVertexPtr prodVtx =
p.genParticle()->production_vertex();
46 if (prodVtx ==
nullptr)
50 for (
auto part : ptcls)
51 if (ancestor ==
part.genParticle())
60 Particles ptcls = {
p2};
65 bool hasChild(
const ConstGenParticlePtr &ptcl,
int pdgID) {
67 if (
child.pid() == pdgID) {
75 bool hasParent(
const ConstGenParticlePtr &ptcl,
int pdgID) {
77 if (
parent->pdg_id() == pdgID)
84 for (
auto child :
p.children()) {
85 if (PID::isQuark(
child.pid())) {
94 for (
auto child :
p.children()) {
95 if (PID::isChLepton(
child.pid())) {
104 HiggsClassification
error(HiggsClassification &
cat,
107 int NmaxWarnings = 20) {
113 static std::atomic<int> Nwarnings{0};
114 if (!
msg.empty() && ++Nwarnings < NmaxWarnings)
127 HiggsClassification
cat;
128 cat.prodMode = prodMode;
145 "Unkown Higgs production mechanism. Cannot classify event."
146 " Classification for all events will most likely fail.");
154 ConstGenVertexPtr HSvtx =
event.genEvent()->signal_process_vertex();
158 if (!PID::isHiggs(ptcl->pdg_id()))
161 if (ptcl->end_vertex() && !
hasChild(ptcl, PID::HIGGS)) {
167 if (HSvtx ==
nullptr && ptcl->production_vertex() && !
hasParent(ptcl, PID::HIGGS))
168 HSvtx = ptcl->production_vertex();
175 "Current event has " + std::to_string(Nhiggs) +
" Higgs bosons. There must be only one.");
176 if (
cat.higgs.children().size() < 2)
179 if (HSvtx ==
nullptr)
188 bool is_uncatdV =
false;
189 Particles uncatV_decays;
190 FourMomentum uncatV_p4(0, 0, 0, 0);
191 FourVector uncatV_v4(0, 0, 0, 0);
192 int nWs = 0, nZs = 0, nTop = 0;
193 if (
isVH(prodMode)) {
195 if (PID::isW(ptcl->pdg_id())) {
199 if (PID::isZ(ptcl->pdg_id())) {
208 if (!PID::isHiggs(ptcl->pdg_id())) {
210 uncatV_p4 +=
Particle(ptcl).momentum();
221 if (
isVH(prodMode) && !
cat.V.genParticle()->end_vertex())
224 if (
isVH(prodMode) &&
cat.V.children().size() < 2)
227 if ((prodMode ==
HTXS::WH && (nZs > 0 || nWs != 1)) ||
231 "Found " + std::to_string(nWs) +
" W-bosons and " + std::to_string(nZs) +
232 " Z-bosons. Inconsitent with VH expectation.");
240 if (!PID::isTop(ptcl->pdg_id()))
244 if (top.genParticle()->end_vertex())
245 for (
auto child : top.children())
246 if (PID::isW(
child.pid()))
252 if ((prodMode ==
HTXS::TTH && Ws.size() < 2) || (prodMode ==
HTXS::TH && Ws.empty()))
264 Particles leptonicVs;
269 leptonicVs = uncatV_decays;
271 if (W.genParticle()->end_vertex() && !
quarkDecay(W))
275 const Particles FS = apply<FinalState>(
event,
"FS").particles();
277 FourMomentum sum(0, 0, 0, 0), vSum(0, 0, 0, 0), hSum(0, 0, 0, 0);
283 hSum +=
p.momentum();
288 vSum +=
p.momentum();
296 cat.p4decay_higgs = hSum;
297 cat.p4decay_V = vSum;
300 FastJets
jets(fps_temp, FastJets::ANTIKT, 0.4);
323 cat.isZ2vvDecay =
false;
325 cat.isZ2vvDecay =
true;
352 int getBin(
double x, std::vector<double>
bins) {
353 for (
size_t i = 1;
i <
bins.size(); ++
i)
356 return bins.size() - 1;
365 const FourMomentum &j1 =
jets[0].momentum(), &j2 =
jets[1].momentum();
366 bool VBFtopo = (j1 + j2).
mass() > 400.0 &&
std::abs(j1.rapidity() - j2.rapidity()) > 2.8;
367 return VBFtopo ? (j1 + j2 + higgs.momentum()).
pt() < 25 ? 2 : 1 : 0;
377 const FourMomentum &j1 =
jets[0].momentum(), &j2 =
jets[1].momentum();
378 double mjj = (j1 + j2).
mass();
379 if (mjj > 350 && mjj <= 700)
380 return (j1 + j2 + higgs.momentum()).
pt() < 25 ? 1 : 2;
382 return (j1 + j2 + higgs.momentum()).
pt() < 25 ? 3 : 4;
396 const FourMomentum &j1 =
jets[0].momentum(), &j2 =
jets[1].momentum();
397 double mjj = (j1 + j2).
mass();
398 if (mjj > 350 && mjj <= 700)
399 return (j1 + j2 + higgs.momentum()).
pt() < 25 ? 1 : 2;
400 else if (mjj > 700 && mjj <= 1000)
401 return (j1 + j2 + higgs.momentum()).
pt() < 25 ? 3 : 4;
402 else if (mjj > 1000 && mjj <= 1500)
403 return (j1 + j2 + higgs.momentum()).
pt() < 25 ? 5 : 6;
405 return (j1 + j2 + higgs.momentum()).
pt() < 25 ? 7 : 8;
418 int ctrlHiggs =
std::abs(higgs.rapidity()) < 2.5;
435 int Njets =
jets.size(), ctrlHiggs =
std::abs(higgs.rapidity()) < 2.5, fwdHiggs = !ctrlHiggs;
436 double pTj1 = !
jets.empty() ?
jets[0].momentum().pt() : 0;
448 else if (
Njets >= 2) {
450 if (higgs.pt() <= 200) {
453 else if (vbfTopo == 1)
462 if (
std::abs(higgs.rapidity()) > 2.5)
471 if (60 < mjj && mjj < 120)
479 else if (
V.pt() < 150)
481 else if (
V.pt() > 250)
490 else if (
V.pt() < 150)
492 else if (
V.pt() > 250)
503 else if (
jets.empty())
523 int Njets =
jets.size(), ctrlHiggs =
std::abs(higgs.rapidity()) < 2.5, fwdHiggs = !ctrlHiggs;
531 if (higgs.pt() > 200)
548 if (
std::abs(higgs.rapidity()) > 2.5)
555 else if (
Njets >= 2) {
559 else if (60 < mjj && mjj < 120)
561 else if (120 < mjj && mjj < 350)
563 else if (mjj > 350) {
564 if (higgs.pt() > 200)
575 else if (
V.pt() < 75)
577 else if (
V.pt() < 150)
579 else if (
V.pt() > 250)
588 else if (
V.pt() < 75)
590 else if (
V.pt() < 150)
592 else if (
V.pt() > 250)
601 else if (
V.pt() < 75)
603 else if (
V.pt() < 150)
605 else if (
V.pt() > 250)
625 int Njets =
jets.size(), ctrlHiggs =
std::abs(higgs.rapidity()) < 2.5, fwdHiggs = !ctrlHiggs;
633 if (higgs.pt() > 200)
641 double pTHjj = (
jets[0].momentum() +
jets[1].momentum() + higgs.momentum()).
pt();
655 if (
std::abs(higgs.rapidity()) > 2.5)
662 else if (
Njets >= 2) {
664 double pTHjj = (
jets[0].momentum() +
jets[1].momentum() + higgs.momentum()).
pt();
671 if (higgs.pt() < 200) {
728 int Njets =
jets.size(), ctrlHiggs =
std::abs(higgs.rapidity()) < 2.5, fwdHiggs = !ctrlHiggs;
736 if (higgs.pt() > 200)
753 if (
std::abs(higgs.rapidity()) > 2.5)
760 else if (
Njets >= 2) {
764 else if (60 < mjj && mjj < 120)
766 else if (120 < mjj && mjj < 350)
768 else if (mjj > 350) {
769 if (higgs.pt() > 200)
780 else if (
V.pt() < 75)
782 else if (
V.pt() < 150)
784 else if (
V.pt() > 250)
793 else if (
V.pt() < 75)
795 else if (
V.pt() < 150)
797 else if (
V.pt() > 250)
806 else if (
V.pt() < 75)
808 else if (
V.pt() < 150)
810 else if (
V.pt() > 250)
833 int Njets =
jets.size(), ctrlHiggs =
std::abs(higgs.rapidity()) < 2.5, fwdHiggs = !ctrlHiggs;
841 if (higgs.pt() > 200) {
843 double pTHj = (
jets[0].momentum() + higgs.momentum()).
pt();
844 if (pTHj / higgs.pt() > 0.15)
857 double pTHjj = (
jets[0].momentum() +
jets[1].momentum() + higgs.momentum()).
pt();
871 if (
std::abs(higgs.rapidity()) > 2.5)
878 else if (
Njets >= 2) {
880 double pTHjj = (
jets[0].momentum() +
jets[1].momentum() + higgs.momentum()).
pt();
887 if (higgs.pt() < 200) {
952 void init()
override {
953 printf(
"==============================================================\n");
954 printf(
"======== HiggsTemplateCrossSections Initialization =========\n");
955 printf(
"==============================================================\n");
959 char *pm_env = std::getenv(
"HIGGSPRODMODE");
960 string pm(pm_env ==
nullptr ?
"" : pm_env);
963 else if (pm ==
"VBF")
969 else if (pm ==
"QQ2ZH")
971 else if (pm ==
"GG2ZH")
973 else if (pm ==
"TTH")
975 else if (pm ==
"BBH")
980 MSG_WARNING(
"No HIGGSPRODMODE shell variable found. Needed when running Rivet stand-alone.");
992 printf(
"==============================================================\n");
994 printf(
"======== Sucessful Initialization =========\n");
995 printf(
"==============================================================\n");
1004 const double weight = 1.0;
1007 int F =
cat.stage0_cat % 10,
P =
cat.stage1_cat_pTjet30GeV / 100;
1011 vector<int>
offset({0, 1, 13, 19, 24, 29, 33, 35, 37, 39});
1017 static vector<int> offset1_2({0, 1, 18, 29, 35, 41, 47, 53, 55, 57});
1018 int off1_2 = offset1_2[
P];
1020 static vector<int> offset1_2f({0, 1, 29, 54, 70, 86, 102, 109, 111, 113});
1021 int off1_2f = offset1_2f[
P];
1038 if (!
cat.jets30.empty())
1040 if (
cat.jets30.size() >= 2) {
1041 const FourMomentum &j1 =
cat.jets30[0].momentum(), &j2 =
cat.jets30[1].momentum();
1049 MSG_INFO(
" ====================================================== ");
1050 MSG_INFO(
" Higgs Template X-Sec Categorization Tool ");
1051 MSG_INFO(
" Status Code Summary ");
1052 MSG_INFO(
" ====================================================== ");
1058 MSG_INFO(
" >>>> --> the following errors occured:");
1062 <<
" failed to identify a valid Higgs boson.");
1064 <<
" failed to identify the hard scatter vertex.");
1067 <<
" failed to identify valid Ws from top decay.");
1069 MSG_INFO(
" ====================================================== ");
1070 MSG_INFO(
" ====================================================== ");
1143 #ifdef RIVET_ANALYSIS_PATH