5#ifndef TRUTHRIVETTOOLS_HIGGSTEMPLATECROSSSECTIONS_H
6#define TRUTHRIVETTOOLS_HIGGSTEMPLATECROSSSECTIONS_H
9#include "Rivet/Analysis.hh"
10#include "Rivet/Particle.hh"
11#include "Rivet/Projections/FastJets.hh"
18#include "TLorentzVector.h"
39 :
Analysis(
"HiggsTemplateCrossSections"),
51 if ( ptcl.genParticle()->end_vertex() ) {
52 if ( !
hasChild(ptcl.genParticle(),ptcl.pid()) )
return ptcl;
60 auto prodVtx = p.genParticle()->production_vertex();
61 if (prodVtx ==
nullptr)
return false;
63 for (
auto ancestor:Rivet::HepMCUtils::particles(std::move(prodVtx),Relatives::ANCESTORS)){
64 for (
const auto & part:ptcls )
65 if ( ancestor==part.genParticle() )
return true;
78 for (
const Particle& child:Particle(*ptcl).children())
79 if (child.pid()==pdgID)
return true;
85 for (
auto parent:Rivet::HepMCUtils::particles(ptcl->production_vertex(),Relatives::PARENTS))
86 if (parent->pdg_id()==pdgID)
return true;
92 for (
const Particle& child:p.children())
93 if (PID::isQuark(child.pid()))
return true;
99 for (
const Particle& child:p.children())
101#
if RIVET_VERSION_CODE >= 40000
102 PID::isChargedLepton(child.pid())
104 PID::isChLepton(child.pid())
113 std::string_view
msg={},
int NmaxWarnings=20)
const {
116 const auto errIndex =
static_cast<std::size_t
>(err);
117 if (errIndex < std::size(m_errorCount)) {
118 ++m_errorCount[errIndex];
120 MSG_WARNING(
"Invalid HTXS error code: " << errIndex);
123 static std::atomic<int> Nwarnings = 0;
124 if ( !
msg.empty() && ++Nwarnings < NmaxWarnings )
135 HiggsClassification cat;
136 cat.prodMode = prodMode;
154 "Unkown Higgs production mechanism. Cannot classify event."
155 " Classification for all events will most likely fail.");
165 for (
auto ptcl : Rivet::HepMCUtils::particles(event.genEvent()) ) {
168 if ( !PID::isHiggs(ptcl->pdg_id()) )
continue;
170 if ( ptcl->end_vertex() && !
hasChild(ptcl,PID::HIGGS) ) {
171 cat.higgs = Particle(ptcl); ++Nhiggs;
175 if ( HSvtx==
nullptr && ptcl->production_vertex() && !
hasParent(ptcl,PID::HIGGS) )
176 HSvtx = ptcl->production_vertex();
182 "Current event has "+std::to_string(Nhiggs)+
" Higgs bosons. There must be only one.");
183 if (cat.higgs.children().size()<2)
185 "Could not identify Higgs boson decay products.");
187 if (HSvtx ==
nullptr)
196 bool is_uncatdV =
false;
197 Particles uncatV_decays;
198 FourMomentum uncatV_p4(0,0,0,0);
199 FourVector uncatV_v4(0,0,0,0);
201 if (
isVH(prodMode) ) {
202 for (
auto ptcl:Rivet::HepMCUtils::particles(HSvtx,Relatives::CHILDREN)) {
203 if (PID::isW(ptcl->pdg_id())) { ++nWs; cat.V=Particle(ptcl); }
204 if (PID::isZ(ptcl->pdg_id())) { ++nZs; cat.V=Particle(std::move(ptcl)); }
208 for (
auto ptcl:Rivet::HepMCUtils::particles(HSvtx,Relatives::CHILDREN)) {
209 if (!PID::isHiggs(ptcl->pdg_id())) {
210 uncatV_decays += Particle(ptcl);
211 uncatV_p4 += Particle(ptcl).momentum();
212 uncatV_v4 += Particle(std::move(ptcl)).origin();
215 is_uncatdV =
true; cat.V = Particle(24,uncatV_p4,uncatV_v4);
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) ) ||
230 std::to_string(nZs)+
" Z-bosons. Inconsitent with VH expectation.");
237 for (
auto ptcl : Rivet::HepMCUtils::particles(HSvtx,Relatives::CHILDREN) ) {
238 if ( !PID::isTop(ptcl->pdg_id()) )
continue;
240 if ( top.genParticle()->end_vertex() )
241 for (
const auto &child:top.children())
247 if ( (prodMode==
HTXS::TTH && Ws.size()<2) || (prodMode==
HTXS::TH && Ws.size()<1 ) )
252 for (
auto ptcl : Rivet::HepMCUtils::particles(std::move(HSvtx),Relatives::CHILDREN) ) {
253 if (PID::isW(ptcl->pdg_id())) {
269 Particles leptonicVs;
272 }
else leptonicVs = std::move(uncatV_decays);
273 for (
const auto & W:Ws )
if ( W.genParticle()->end_vertex() && !
quarkDecay(W) ) leptonicVs += W;
276 const Particles FS = apply<FinalState>(event,
"FS").particles();
278 Particles decayparticles;
280 FourMomentum sum(0,0,0,0), vSum(0,0,0,0), hSum(0,0,0,0);
281 for (
const Particle &p : FS ) {
285 if (
originateFrom(p,cat.higgs) ) { hSum += p.momentum(); decayparticles += p;
continue; }
287 if (
isVH(prodMode) && !is_uncatdV &&
originateFrom(p,Ws) ) vSum += p.momentum();
289 if ( leptonicVs.size() &&
originateFrom(p,leptonicVs) )
continue;
294 cat.p4decay_higgs = hSum;
295 cat.p4decay_V = vSum;
298 FastJets jets(fps_temp,
299#
if RIVET_VERSION_CODE >= 40000
307 cat.jets25 = jets.jetsByPt( Cuts::pT > 25.0 );
308 cat.jets30 = jets.jetsByPt( Cuts::pT > 30.0 );
313 std::to_string(sum.pt())+
" GeV and m = "+std::to_string(sum.mass())+
" GeV");
326 cat.isZ2vvDecay =
false;
329 cat.stage1_cat_pTjet25GeV =
getStage1Category(prodMode,cat.higgs,cat.jets25,cat.V);
330 cat.stage1_cat_pTjet30GeV =
getStage1Category(prodMode,cat.higgs,cat.jets30,cat.V);
356 throw std::invalid_argument(
"Input value is out of bin range or bins vector is empty.");
359 for (
size_t i = 1; i <
bins.size(); ++i) {
361 return static_cast<int>(i - 1);
365 return static_cast<int>(
bins.size() - 1);
372 if (jets.size()<2)
return 0;
373 const FourMomentum &j1=jets[0].momentum(), &j2=jets[1].momentum();
374 bool VBFtopo = (j1+j2).mass() > 400.0 && std::abs(j1.rapidity()-j2.rapidity()) > 2.8;
375 return VBFtopo ? (j1+j2+higgs.momentum()).pt()<25 ? 2 : 1 : 0;
382 if (jets.size()<2)
return 0;
383 const FourMomentum &j1=jets[0].momentum(), &j2=jets[1].momentum();
384 double mjj = (j1+j2).mass();
385 if(mjj>350 && mjj<=700)
return (j1+j2+higgs.momentum()).pt()<25 ? 1 : 2;
386 else if(mjj>700)
return (j1+j2+higgs.momentum()).pt()<25 ? 3 : 4;
396 if (jets.size()<2)
return 0;
397 const FourMomentum &j1=jets[0].momentum(), &j2=jets[1].momentum();
398 double mjj = (j1+j2).mass();
399 if(mjj>350 && mjj<=700)
return (j1+j2+higgs.momentum()).pt()<25 ? 1 : 2;
400 else if(mjj>700 && mjj<=1000)
return (j1+j2+higgs.momentum()).pt()<25 ? 3 : 4;
401 else if(mjj>1000 && mjj<=1500)
return (j1+j2+higgs.momentum()).pt()<25 ? 5 : 6;
402 else if(mjj>1500)
return (j1+j2+higgs.momentum()).pt()<25 ? 7 : 8;
409 if (jets.size() < 2)
return 0;
410 const FourMomentum &j1 = jets[0].momentum(), &j2 = jets[1].momentum();
411 double mjj = (j1 + j2).mass();
412 double pthjj = (j1 + j2 + higgs.momentum()).pt();
418 int mjj_pthjj_bin = 0;
419 if (mjj > 350 && mjj <= 700)
420 mjj_pthjj_bin = pthjj < 25 ? 1 : 2;
421 else if (mjj > 700 && mjj <= 1000)
422 mjj_pthjj_bin = pthjj < 25 ? 3 : 4;
423 else if (mjj > 1000 && mjj <= 1500)
424 mjj_pthjj_bin = pthjj < 25 ? 5 : 6;
426 mjj_pthjj_bin = pthjj < 25 ? 7 : 8;
430 constexpr double pi = 3.14159265358979323846;
431 int deltaphijj_bin = mjj > 350 ? 8*
getBin(deltaphijj, {-1*
pi, -0.5*
pi, 0, 0.5*
pi,
pi}) : 0;
433 return deltaphijj_bin + mjj_pthjj_bin;
442 const Particle &higgs,
443 const Particle &V)
const {
445 int ctrlHiggs = std::abs(higgs.rapidity())<2.5;
453 return Category(prodMode*10 + ctrlHiggs);
458 const Particle &higgs,
460 const Particle &V)
const {
462 int Njets=jets.size(), ctrlHiggs = std::abs(higgs.rapidity())<2.5, fwdHiggs = !ctrlHiggs;
463 double pTj1 = jets.size() ? jets[0].momentum().pt() : 0;
484 if (std::abs(higgs.rapidity())>2.5)
return QQ2HQQ_FWDH;
488 double mjj = jets.size()>1 ? (jets[0].mom()+jets[1].mom()).mass():0;
524 const Particle &higgs,
526 const Particle &V)
const {
528 int Njets=jets.size(), ctrlHiggs = std::abs(higgs.rapidity())<2.5, fwdHiggs = !ctrlHiggs;
548 if (std::abs(higgs.rapidity())>2.5)
return QQ2HQQ_FWDH;
549 int Njets=jets.size();
553 double mjj = (jets[0].mom()+jets[1].mom()).mass();
557 else if ( mjj > 350 ) {
601 const Particle &higgs,
603 const Particle &V)
const {
605 int Njets=jets.size(), ctrlHiggs = std::abs(higgs.rapidity())<2.5, fwdHiggs = !ctrlHiggs;
612 if ( higgs.pt()>200 ){
614 double pTHj = (jets[0].momentum()+higgs.momentum()).pt();
624 double pTHjj = (jets[0].momentum()+jets[1].momentum()+higgs.momentum()).pt();
635 if (std::abs(higgs.rapidity())>2.5)
return QQ2HQQ_FWDH;
636 int Njets=jets.size();
640 double mjj = (jets[0].mom()+jets[1].mom()).mass();
641 double pTHjj = (jets[0].momentum()+jets[1].momentum()+higgs.momentum()).pt();
657 int Njets=jets.size();
665 int Njets=jets.size();
673 int Njets=jets.size();
689 const Jets &jets,
const Particle &V)
const {
697 int Njets = jets.size(), ctrlHiggs = std::abs(higgs.rapidity()) < 2.5, fwdHiggs = !ctrlHiggs;
715 if (std::abs(higgs.rapidity()) > 2.5)
return QQ2HQQ_FWDH;
716 int Njets = jets.size();
721 else if (Njets >= 2) {
722 double mjj = (jets[0].mom() + jets[1].mom()).mass();
725 else if (60 < mjj && mjj < 120)
727 else if (120 < mjj && mjj < 350)
729 else if (mjj > 350) {
730 if (higgs.pt() > 200)
740 else if (V.pt() < 75)
742 else if (V.pt() < 150)
744 else if (V.pt() < 250)
746 else if (V.pt() < 400)
748 else if (V.pt() < 600)
756 else if (V.pt() < 75)
758 else if (V.pt() < 150)
760 else if (V.pt() < 250)
762 else if (V.pt() < 400)
764 else if (V.pt() < 600)
772 else if (V.pt() < 75)
774 else if (V.pt() < 150)
776 else if (V.pt() < 250)
778 else if (V.pt() < 400)
780 else if (V.pt() < 600)
797 const Jets &jets,
const Particle &V,
const bool isTHW)
const {
805 int Njets = jets.size(), ctrlHiggs = std::abs(higgs.rapidity()) < 2.5, fwdHiggs = !ctrlHiggs;
811 if (higgs.pt() > 200) {
813 double pthj = (jets[0].momentum() + higgs.momentum()).pt();
814 if (pthj / higgs.pt() > 0.15)
824 double mjj = (jets[0].mom()+jets[1].mom()).mass();
825 double pthjj = (jets[0].momentum() + jets[1].momentum() + higgs.momentum()).pt();
839 if (std::abs(higgs.rapidity()) > 2.5)
return QQ2HQQ_FWDH;
840 int Njets = jets.size();
845 else if (Njets >= 2) {
846 double mjj = (jets[0].mom() + jets[1].mom()).mass();
847 double pthjj = (jets[0].momentum() + jets[1].momentum() + higgs.momentum()).pt();
849 if (higgs.pt() < 200){
861 if (higgs.pt() < 200)
863 else if (higgs.pt() < 450)
874 int Njets = jets.size();
883 int Njets = jets.size();
892 int Njets = jets.size();
918 const Particles &decayparticles,
919 std::vector<float> &decay_observables,
920 int &cuts_passed)
const {
923 decay_observables = std::vector<float>(11, -999);
934 auto &higgsmom = higgs.momentum();
936 double higgsm2 = higgsmom.invariant();
937 double higgsm = (higgsm2 > 0 ? sqrt(higgsm2) : 0);
939 const int N =
static_cast<int>(decayparticles.size());
940 std::vector<double> Ep(N), pp(N);
941 std::vector<std::vector<double>> cosangle(N, std::vector<double>(N, 1.0));
943 LorentzTransform toHiggs = LorentzTransform::mkFrameTransform(higgsmom);
944 for (
int i = 0; i < N; ++i) {
945 auto &mom = decayparticles[i].momentum();
946 double m2 = mom.invariant();
947 double hp = higgsmom * mom;
949 double p2v = Ep[i] * Ep[i] - m2;
950 pp[i] = (p2v > 0 ? sqrt(p2v) : 0);
951 for (
int j = 0; j < i; ++j) {
952 auto &mom2 = decayparticles[j].momentum();
953 cosangle[i][j] = (Ep[i]*Ep[j] - mom*mom2) / (pp[i]*pp[j]);
954 cosangle[j][i] = cosangle[i][j];
959 Particles dp_rest = decayparticles;
960 for (
int i = 0; i < N; ++i)
961 dp_rest[i] = dp_rest[i].transformBy(toHiggs);
964 std::vector<FourMomentum> v_p4{};
965 std::vector<int> v_pid{};
970 cuts_passed =
findZZ4ldecay(std::move(v_p4), std::move(v_pid), decay_observables);
971 bool isZZ4l = (cuts_passed & 0b111111) == 0b111111;
975 switch ((cuts_passed >> 6) & 0b11) {
976 case 0b01:
return HZZ4e;
979 case 0b00:
MSG_WARNING(
"Found HZZ4l event but unable to categorise. This shouldn't happen!");
991 const std::vector<std::vector<double>> &cosangle,
992 std::vector<FourMomentum> &v_p4,
993 std::vector<int> &v_pid)
const {
994 const double cos_cut = cos(0.1);
997 std::vector<std::vector<int>> dressers(dp.size());
1000 for (
size_t i = 0; i < dp.size(); i++) {
1001 const Particle &p = dp[i];
1002 if (p.pid() != 22)
continue;
1003 int max_cos_index = -1;
1004 for (
size_t j = 0; j < dp.size(); j++) {
1005 if (!(PID::isElectron(dp[j].pid()) || PID::isMuon(dp[j].pid())))
continue;
1006 if (cosangle[i][j] < cos_cut)
continue;
1007 if (max_cos_index != -1 && cosangle[i][j] < cosangle[i][max_cos_index])
continue;
1010 if(max_cos_index != -1)
1011 dressers[max_cos_index].push_back(i);
1013 v_p4.push_back(p.momentum());
1014 v_pid.push_back(p.pid());
1019 for (
size_t i = 0; i < dp.size(); i++) {
1020 const Particle &p = dp[i];
1021 if (!(PID::isElectron(p.pid()) || PID::isMuon(p.pid())))
continue;
1022 v_p4.push_back(p.momentum());
1023 v_pid.push_back(p.pid());
1024 for (
auto photon : dressers[i]) {
1025 v_p4.back() += dp[photon].momentum();
1037 std::vector<int> v_pid,
1038 std::vector<float> &decay_observables)
const {
1041 for (
int pid : v_pid) lepton_num += (std::abs(pid) == 11 || std::abs(pid) == 13);
1043 std::vector<int> lepton_index{};
1045 unsigned char cut_passed = 0;
1047 cut_passed |= (lepton_num >= 4);
1052 FourMomentum
hsum{};
1053 for (
uint i = 0; i < v_pid.size(); ++i) {
1054 if (std::abs(v_pid[i]) == 11 || std::abs(v_pid[i]) == 13) {
1059 cut_passed |= (
hsum.mass() > 105 &&
hsum.mass() < 130) << 5;
1063 if(lepton_index.size() == 4) {
1064 if (PID::isElectron(v_pid[lepton_index[0]]) || PID::isElectron(v_pid[lepton_index[2]]))
1065 cut_passed |= 0b01000000;
1066 if (PID::isMuon(v_pid[lepton_index[0]]) || PID::isMuon(v_pid[lepton_index[2]]))
1067 cut_passed |= 0b10000000;
1077 const std::vector<int> &v_pid)
const {
1079 std::vector<FourMomentum> v_p4_lepton = v_p4;
1081 const double cos_cut = cos(0.1);
1083 for (
uint i = 0; i < v_p4_lepton.size(); ++i) {
1084 if ( !(PID::isMuon(v_pid[i]) || PID::isElectron(v_pid[i])) )
continue;
1085 for (
uint j = 0; j < i; ++j) {
1086 if ( !(PID::isMuon(v_pid[j]) || PID::isElectron(v_pid[j])) )
continue;
1087 double ca = (v_p4_lepton[i].E()*v_p4_lepton[j].E() - v_p4_lepton[i]*v_p4_lepton[j])
1088 / (v_p4_lepton[i].p()*v_p4_lepton[j].p());
1089 cos_max = std::max(ca, cos_max);
1092 return cos_cut > cos_max;
1100 const std::vector<int> &v_pid,
1101 std::vector<int> &lepton_index)
const {
1102 std::vector<int> lepIdx;
1103 for (
size_t i = 0; i < v_pid.size(); ++i)
1104 if (std::abs(v_pid[i]) == 11 || std::abs(v_pid[i]) == 13) lepIdx.push_back(i);
1105 if (lepIdx.size() < 2)
return 0b00;
1107 const double mZ = 91.1876;
1109 double bestDM = 1e30;
1110 double bestM12 = -1, bestM34 = -1;
1111 size_t bestpair[4] = {999, 999, 999, 999};
1112 for (
size_t i = 0; i < lepIdx.size(); i++) {
1113 for (
size_t j = i+1; j < lepIdx.size(); j++) {
1114 int a=lepIdx[i], b=lepIdx[j];
1115 if(v_pid[
a] != -v_pid[b])
continue;
1116 double m12cur = (v_p4[
a] + v_p4[b]).mass();
1117 if (std::fabs(m12cur - mZ) >= bestDM)
continue;
1118 bestDM = std::fabs(m12cur - mZ);
1119 bestpair[0] = i; bestpair[1] = j;
1125 for (
size_t i = 0; i < lepIdx.size(); i++) {
1126 if (i == bestpair[0] || i == bestpair[1])
continue;
1127 for (
size_t j = i+1; j < lepIdx.size(); j++) {
1128 if (j == bestpair[0] || j == bestpair[1])
continue;
1130 int a=lepIdx[i], b=lepIdx[j];
1131 if(v_pid[
a] != -v_pid[b])
continue;
1132 double m34cur = (v_p4[
a] + v_p4[b]).mass();
1133 if (m34cur <= bestM34)
continue;
1134 bestpair[2] = i; bestpair[3] = j;
1139 if (bestpair[0] == 999) {
1140 MSG_WARNING(
"Unable to find lepton pairings, returning null");
1144 for (
int i = 0; i < 4; i++) {
1145 if (bestpair[i] == 999)
break;
1146 if(v_pid[lepIdx[bestpair[i]]] < 0 && ((i % 2) == 0)) {
1149 lepton_index.push_back(lepIdx[bestpair[i]]);
1159 std::vector<int> &v_pid)
const {
1163 for (
int pid : v_pid) lepton_num += (std::abs(pid) == 11 || std::abs(pid) == 13);
1164 return lepton_num >= 4;
1170 std::vector<int> &v_pid)
const {
1171 float mij_min = 5.0;
1172 size_t min_pair[2] = {999, 999};
1173 for (
size_t i = 0; i < v_p4.size(); i++) {
1174 for (
size_t j = i+1; j < v_p4.size(); j++) {
1175 if (v_pid[i] + v_pid[j] != 0)
continue;
1176 if (!(PID::isMuon(v_pid[i]) || PID::isElectron(v_pid[i])))
continue;
1177 float mij = (v_p4[i] + v_p4[j]).mass();
1178 if (mij >= mij_min)
continue;
1184 if (min_pair[0] == 999)
return false;
1185 v_p4.erase(v_p4.begin() + min_pair[1]);
1186 v_p4.erase(v_p4.begin() + min_pair[0]);
1188 v_pid.erase(v_pid.begin() + min_pair[1]);
1189 v_pid.erase(v_pid.begin() + min_pair[0]);
1196 const std::vector<int> &v_4l_index,
1197 std::vector<float> &decay_observable)
const {
1199 if (v_4l_index.size() != 4) {
1200 if (v_4l_index.size() >= 2) decay_observable[0] = (v_p4[v_4l_index[0]] + v_p4[v_4l_index[1]]).mass();
1204 FourMomentum v1 = (v_p4[v_4l_index[0]]);
1205 FourMomentum v2 = (v_p4[v_4l_index[1]]);
1206 FourMomentum v3 = (v_p4[v_4l_index[2]]);
1207 FourMomentum v4 = (v_p4[v_4l_index[3]]);
1209 float Z1m = (v1 + v2).mass();
1210 float Z2m = (v3 + v4).mass();
1212 float m14 = (v1 + v4).mass();
1213 float m23 = (v2 + v3).mass();
1214 float m13 = (v1 + v3).mass();
1215 float m24 = (v2 + v4).mass();
1217 FourMomentum Z1 = ( v1 + v2 );
1218 FourMomentum Z2 = ( v3 + v4 );
1220 Vector3 z1 = Z1.vector3().unit();
1221 Vector3 z2 = Z2.vector3().unit();
1224 float cthstr = z1.z();
1226 Vector3 v1p = v1.vector3();
1227 Vector3 v2p = v2.vector3();
1228 Vector3 v3p = v3.vector3();
1229 Vector3 v4p = v4.vector3();
1230 Vector3 nz(0, 0, 1.);
1233 Vector3 n1p = v1p.cross(v2p).unit();
1234 Vector3 n2p = v3p.cross(v4p).unit();
1235 Vector3 nscp = nz.cross(z1).unit();
1236 float phi = (z1.dot(n1p.cross(n2p)) / std::fabs(z1.dot(n1p.cross(n2p))) *
1237 std::acos(-n1p.dot(n2p)));
1238 float phi1 = (z1.dot(n1p.cross(nscp)) / std::fabs(z1.dot(n1p.cross(nscp))) *
1239 std::acos(n1p.dot(nscp)));
1242 LorentzTransform toZ1 = LorentzTransform::mkFrameTransform(Z1);
1243 LorentzTransform toZ2 = LorentzTransform::mkFrameTransform(Z2);
1245 FourMomentum Z2_rfr_Z1 = toZ1.transform(Z2);
1246 Vector3 z2_rfr_Z1 = Z2_rfr_Z1.vector3();
1248 FourMomentum Z1_rfr_Z2 = toZ2.transform(Z1);
1249 Vector3 z1_rfr_Z2 = Z1_rfr_Z2.vector3();
1251 FourMomentum v1_rfr_Z1 = toZ1.transform(v1);
1253 FourMomentum v3_rfr_Z2 = toZ2.transform(v3);
1255 float cth1 = -(z2_rfr_Z1.dot(v1_rfr_Z1.vector3()) /
1256 std::fabs(z2_rfr_Z1.mod() * v1_rfr_Z1.vector3().mod()));
1257 float cth2 = -(z1_rfr_Z2.dot(v3_rfr_Z2.vector3()) /
1258 std::fabs(z1_rfr_Z2.mod() * v3_rfr_Z2.vector3().mod()));
1260 decay_observable[0] = Z1m;
1261 decay_observable[1] = Z2m;
1262 decay_observable[2] = cthstr;
1263 decay_observable[3] =
phi;
1264 decay_observable[4] = phi1;
1265 decay_observable[5] = cth1;
1266 decay_observable[6] = cth2;
1267 decay_observable[7] = m14;
1268 decay_observable[8] = m23;
1269 decay_observable[9] = m13;
1270 decay_observable[10] = m24;
1275 bool passm12(
double m)
const {
return (m > 50.0 && m < 106.0); }
1278 bool passm34(
double m)
const {
return (m > 12.0 && m < 115.0); }
1296 printf(
"==============================================================\n");
1297 printf(
"======== HiggsTemplateCrossSections Initialization =========\n");
1298 printf(
"==============================================================\n");
1302 char *pm_env = getenv(
"HIGGSPRODMODE");
1303 string pm(pm_env==
nullptr?
"":pm_env);
1314 MSG_WARNING(
"No HIGGSPRODMODE shell variable found. Needed when running Rivet stand-alone.");
1319 const FinalState FS;
1325 printf(
"==============================================================\n");
1327 printf(
"======== Sucessful Initialization =========\n");
1328 printf(
"==============================================================\n");
1338 const double weight = 1.;
1341 int F=cat.stage0_cat%10,
P=cat.stage1_cat_pTjet30GeV/100;
1345 static const vector<int> offset({0,1,13,19,24,29,33,35,37,39});
1346 int off = offset[
P];
1348 static const vector<int> offset1_2({0,1,18,29,35,41,47,53,55,57});
1349 int off1_2 = offset1_2[
P];
1351 static const vector<int> offset1_2_Fine({0,1,29,54,70,86,102,109,111,113});
1352 int off1_2_Fine = offset1_2_Fine[
P];
1354 static const vector<int> offset1_3({0,1,26,41,50,59,68,76,101,103});
1355 int off1_3 = offset1_3[
P];
1357 static const vector<int> offset1_3_fine({0,1,63,149,168,187,206,214,276,280});
1358 int off1_3_fine = offset1_3_fine[
P];
1383 if (cat.jets30.size())
m_hist_pT_jet1->fill(cat.jets30[0].pt(),weight);
1384 if (cat.jets30.size()>=2) {
1385 const FourMomentum &j1 = cat.jets30[0].momentum(), &j2 = cat.jets30[1].momentum();
1388 m_hist_pT_Hjj->fill((j1+j2+cat.higgs.momentum()).pt(),weight);
1393 MSG_INFO (
" ====================================================== ");
1394 MSG_INFO (
" Higgs Template X-Sec Categorization Tool ");
1395 MSG_INFO (
" Status Code Summary ");
1396 MSG_INFO (
" ====================================================== ");
1397 bool allSuccess = (numEvents()==m_errorCount[
HTXS::SUCCESS]);
1398 if ( allSuccess )
MSG_INFO (
" >>>> All "<< m_errorCount[
HTXS::SUCCESS] <<
" events successfully categorized!");
1401 MSG_INFO (
" >>>> --> the following errors occured:");
1409 MSG_INFO (
" ====================================================== ");
1410 MSG_INFO (
" ====================================================== ");
1417 for (
auto hist:{
m_hist_stage0,
m_hist_stage1_pTjet25,
m_hist_stage1_pTjet30,
m_hist_stage1_2_pTjet25,
m_hist_stage1_2_pTjet30,
m_hist_stage1_2_fine_pTjet25,
m_hist_stage1_2_fine_pTjet30,
m_hist_stage1_3_pTjet25,
m_hist_stage1_3_pTjet30,
m_hist_stage1_3_fine_pTjet25,
m_hist_stage1_3_fine_pTjet30,
1476#ifdef RIVET_ANALYSIS_PATH
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
Scalar phi() const
phi method
static const std::vector< std::string > bins
double hsum(TH1 *h)
sum the bin contents including the over and underflow bins
Define macros for attributes used to control the static checker.
Rivet routine for classifying MC events according to the Higgs template cross section categories.
int doAngleDressing(const Particles &dp, const std::vector< std::vector< double > > &cosangle, std::vector< FourMomentum > &v_p4, std::vector< int > &v_pid) const
dress leptons with photons within a 0.1 radian angle.
Histo1DPtr m_hist_Njets25
bool ZZ4langle_cut(const std::vector< FourMomentum > &v_p4, const std::vector< int > &v_pid) const
Reject lepton pairs whose opening angle is too small (cos > cos(0.1)).
int vbfTopology_Stage1_2_Fine(const Jets &jets, const Particle &higgs) const
VBF topology selection for Stage1_2 0 = fail loose selection: m_jj > 350 GeV 1 pass loose,...
HiggsTemplateCrossSections()
bool calculate_decay_observables(const std::vector< FourMomentum > &v_p4, const std::vector< int > &v_4l_index, std::vector< float > &decay_observable) const
calculate the relevant 4l decay observables
HiggsClassification classifyEvent(const Event &event, const HTXS::HiggsProdMode prodMode, const HTXS::HiggsDecayMode decayMode) const
Main classificaion method.
Histo1DPtr m_hist_stage1_2_fine_pTjet30
Histo1DPtr m_hist_stage1_3_pTjet25
HiggsClassification error(HiggsClassification &cat, HTXS::ErrorCode err, std::string_view msg={}, int NmaxWarnings=20) const
Returns the classification object with the error code set.
HTXS::HiggsProdMode m_HiggsProdMode
Histo1DPtr m_hist_stage1_2_fine_pTjet25
Histo1DPtr m_hist_stage1_pTjet30
bool originateFrom(const Particle &p, const Particle &p2) const
Whether particle p originates from p2.
void setHiggsProdMode(HTXS::HiggsProdMode prodMode)
Sets the Higgs production mode.
void init()
default Rivet Analysis::init method Booking of histograms, initializing Rivet projection Extracts Hig...
Histo1DPtr m_hist_stage1_2_pTjet30
bool originateFrom(const Particle &p, const Particles &ptcls) const
Whether particle p originate from any of the ptcls.
Histo1DPtr m_hist_y_Higgs
int vbfTopology_Stage1_2(const Jets &jets, const Particle &higgs) const
VBF topology selection 0 = fail loose selection: m_jj > 350 GeV 1 pass loose, but fail additional cut...
HTXS::Stage1_3::Category getStage1_3_Category(const HTXS::HiggsProdMode prodMode, const Particle &higgs, const Jets &jets, const Particle &V) const
Stage-1.3 categorization.
bool isVH(HTXS::HiggsProdMode p) const
Whether the Higgs is produced in association with a vector boson (VH).
Histo1DPtr m_hist_pT_jet1
unsigned char findZZ4ldecay(std::vector< FourMomentum > v_p4, std::vector< int > v_pid, std::vector< float > &decay_observables) const
Select H->ZZ->4l candidate: 4 charged leptons, net charge=0, combined invariant mass in [105,...
Particle getLastInstance(const Particle &ptcl) const
follow a "propagating" particle and return its last instance
Histo1DPtr m_hist_stage1_3_fine_pTjet25
HTXS::Stage1_2_Fine::Category getStage1_2_Fine_Category(const HTXS::HiggsProdMode prodMode, const Particle &higgs, const Jets &jets, const Particle &V) const
Stage-1.2_Fine categorization.
bool remove_least_mij(std::vector< FourMomentum > &v_p4, std::vector< int > &v_pid) const
removes SFOS lepton pairs with invariant mass < 5GeV removes only the pair with the least invariant m...
bool quarkDecay(const Particle &p) const
Return true is particle decays to quarks.
bool hasParent(HepMC::ConstGenParticlePtr ptcl, int pdgID) const
Checks whether the input particle has a parent with a given PDGID.
int vbfTopology_Stage1_3_Fine(const Jets &jets, const Particle &higgs) const
VBF topology selection for Stage1_3 Includes additional deltaphijj binning.
bool passm34(double m) const
Pass sub-leading lepton-pair mass window [12, 115] GeV.
int getBin(double x, const std::vector< double > &bins) const
Return bin index of x given the provided bin edges. 0=first bin, -1=underflow bin.
void setHiggsDecayMode(HTXS::HiggsDecayMode decayMode)
Sets the Higgs production mode.
Histo1DPtr m_hist_Njets30
bool hasChild(HepMC::ConstGenParticlePtr ptcl, int pdgID) const
Checks whether the input particle has a child with a given PDGID.
Histo1DPtr m_hist_stage1_2_pTjet25
HTXS::Stage1::Category getStage1Category(const HTXS::HiggsProdMode prodMode, const Particle &higgs, const Jets &jets, const Particle &V) const
Stage-1 categorization.
HTXS::Stage1_3_Fine::Category getStage1_3_Fine_Category(const HTXS::HiggsProdMode prodMode, const Particle &higgs, const Jets &jets, const Particle &V, const bool isTHW) const
Stage-1.3 Fine categorization.
Histo1DPtr m_hist_deltay_jj
void printClassificationSummary()
HTXS::Stage0::DecayCategory getStage0DecayCategory(const Particle &higgs, const Particles &decayparticles, std::vector< float > &decay_observables, int &cuts_passed) const
Stage-0 Higgs decay categorization.
HTXS::Stage0::Category getStage0Category(const HTXS::HiggsProdMode prodMode, const Particle &higgs, const Particle &V) const
Stage-0 HTXS categorization.
Histo1DPtr m_hist_dijet_mass
void analyze(const Event &event)
bool ChLeptonDecay(const Particle &p) const
Return true if particle decays to charged leptons.
Histo1DPtr m_hist_stage1_3_fine_pTjet30
bool passm12(double m) const
Pass leading lepton-pair mass window [50, 106] GeV.
HTXS::HiggsDecayMode m_HiggsDecayMode
Histo1DPtr m_hist_stage1_3_pTjet30
Histo1DPtr m_hist_pT_Higgs
HTXS::Stage1_2::Category getStage1_2_Category(const HTXS::HiggsProdMode prodMode, const Particle &higgs, const Jets &jets, const Particle &V) const
Stage-1.2 categorization.
std::array< std::atomic< size_t >, HTXS::NUM_ERRORCODES > m_errorCount ATLAS_THREAD_SAFE
Histo1DPtr m_hist_stage1_pTjet25
int vbfTopology(const Jets &jets, const Particle &higgs) const
VBF topolog selection 0 = fail loose selction: m_jj > 400 GeV and Dy_jj > 2.8 1 pass loose,...
bool ZZ4lJpsi_cut(std::vector< FourMomentum > &v_p4, std::vector< int > &v_pid) const
J/psi veto: reject events with a same-flavour opposite-sign lepton pair with invariant mass below 5 G...
unsigned char ZZ4lm12m34_cut(const std::vector< FourMomentum > &v_p4, const std::vector< int > &v_pid, std::vector< int > &lepton_index) const
Apply m12 and m34 mass window cuts for ZZ->4l selection Also insert the leading lepton pair and suble...
The namespace of all packages in PhysicsAnalysis/JetTagging.
Namespace for Stage0 categorization.
@ QQ2HQQ_GE2J_MJJ_0_60_PTHJJ_GT25
@ GG2H_GE2J_MJJ_0_350_PTH_0_60_PTHJJ_0_25
@ QQ2HQQ_GE2J_MJJ_0_60_PTHJJ_0_25
@ QQ2HQQ_GE2J_MJJ_350_700_PTH_GT200_PTHJJ_0_25
@ GG2H_PTH_200_300_PTHJoverPTH_0_15
@ GG2H_GE2J_MJJ_0_350_PTH_0_60_PTHJJ_GT25
@ GG2H_PTH_200_300_PTHJoverPTH_GT15
Categorization Stage 1.2: Three digit integer of format PF Where P is a digit representing the proces...
@ GG2HLL_PTV_150_250_GE1J
@ QQ2HQQ_GE2J_MJJ_350_700_PTH_0_200_PTHJJ_0_25
@ GG2H_GE2J_MJJ_350_700_PTH_0_200_PTHJJ_0_25
@ QQ2HQQ_GE2J_MJJ_GT350_PTH_GT200
@ GG2H_GE2J_MJJ_0_350_PTH_0_60
@ QQ2HQQ_GE2J_MJJ_120_350
@ QQ2HQQ_GE2J_MJJ_0_60_PTH_0_200_PTHJJ_GT25
@ QQ2HQQ_GE2J_MJJ_0_60_PTH_0_200_PTHJJ_0_25
@ QQ2HQQ_GE2J_MJJ_350_700_PTH_0_200_PTHJJ_0_25_DPHIJJ_MPI_MPIO2
@ GG2H_GE2J_MJJ_350_700_PTH_0_200_PTHJJ_0_25_DPHIJJ_MPI_MPIO2
@ QQ2HQQ_GE2J_MJJ_0_60_PTH_GT200_PTHJJ_0_25
@ QQ2HQQ_GE2J_MJJ_350_700_PTH_200_450_PTHJJ_0_25_DPHIJJ_MPI_MPIO2
@ GG2H_GE2J_MJJ_0_350_PTH_0_30_PTHJJ_0_25
@ QQ2HQQ_GE2J_MJJ_350_700_PTH_GT450
@ QQ2HQQ_GE2J_MJJ_0_60_PTH_GT200_PTHJJ_GT25
@ GG2H_GE2J_MJJ_0_350_PTH_0_30_PTHJJ_GT25
Categorization Stage 1.3: Three digit integer of format PF Where P is a digit representing the proces...
@ QQ2HQQ_GE2J_MJJ_0_60_PTH_0_200
@ QQ2HQQ_GE2J_MJJ_120_350_PTH_GT200
@ GG2H_GE2J_MJJ_0_350_PTH_0_30
@ QQ2HQQ_GE2J_MJJ_120_350_PTH_0_200
@ QQ2HQQ_GE2J_MJJ_GT350_PTH_GT450
@ QQ2HQQ_GE2J_MJJ_60_120_PTH_0_200
@ QQ2HQQ_GE2J_MJJ_GT350_PTH_200_450
@ GG2HLL_PTV_250_400_GE1J
@ QQ2HLNU_PTV_250_400_GE1J
@ QQ2HQQ_GE2J_MJJ_0_60_PTH_GT200
@ QQ2HQQ_GE2J_MJJ_60_120_PTH_GT200
@ QQ2HLL_PTV_250_400_GE1J
Categorization Stage 1: Three digit integer of format PF Where P is a digit representing the process ...
@ QQ2HQQ_VBFTOPO_JET3VETO
@ QQ2HLL_PTV_150_250_GE1J
@ QQ2HLNU_PTV_150_250_GE1J
Higgs Template Cross Section namespace.
HiggsDecayMode
Two digit number of format PF P is digit for the physics process and F is 0 for |yH|>2....
ErrorCode
Error code: whether the classification was successful or failed.
@ HS_VTX_IDENTIFICATION
failed to identify hard scatter vertex
@ PRODMODE_DEFINED
production mode not defined
@ SUCCESS
successful classification
@ VH_DECAY_IDENTIFICATION
failed to identify associated vector boson decay products
@ HIGGS_IDENTIFICATION
failed to identify Higgs boson
@ TOP_W_IDENTIFICATION
failed to identify top decay
@ HIGGS_DECAY_IDENTIFICATION
failed to identify Higgs boson decay products
@ MOMENTUM_CONSERVATION
failed momentum conservation
@ NUM_ERRORCODES
number of error codes (keep this unnumbered and last)
@ VH_IDENTIFICATION
failed to identify associated vector boson
HiggsProdMode
Higgs production modes, corresponding to input sample.
ConstGenVertexPtr signal_process_vertex(const GenEvent *e)
HepMC3::ConstGenParticlePtr ConstGenParticlePtr
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)