13#include "Pythia8/Pythia.h"
17#if PYTHIA_VERSION_INTEGER >= 8310
21# include "Pythia8/Plugins.h"
22# undef PYTHIA8_PLUGIN_CLASS
23# undef PYTHIA8_PLUGIN_VERSIONS
24# define PYTHIA8_PLUGIN_CLASS(BASE, CLASS, PYTHIA, SETTINGS, LOGGER)
25# define PYTHIA8_PLUGIN_VERSIONS(...)
28#include "Pythia8Plugins/PowhegHooks.h"
92 std::cout <<
"**********************************************************" << std::endl;
93 std::cout <<
"* *" << std::endl;
94 std::cout <<
"* Applying PowhegHooksST UserHook (Single-Top)! *" << std::endl;
95 std::cout <<
"* Resonance-aware matching for single-top-dec-pwhg *" << std::endl;
96 std::cout <<
"* *" << std::endl;
97 std::cout <<
"**********************************************************" << std::endl;
112 PowhegHooks::initAfterBeams();
114 if (settingsPtr->isParm(
"POWHEG:pTcutoff")) {
115 m_pTcutoff = settingsPtr->parm(
"POWHEG:pTcutoff");
120 m_vetoMode = settingsPtr->mode(
"POWHEG:veto");
121 m_vetoCount = settingsPtr->mode(
"POWHEG:vetoCount");
124 if (settingsPtr->isMode(
"POWHEG:single-top:emscales")) {
126 }
else if (settingsPtr->isMode(
"POWHEG:emscales")) {
133 std::cout <<
"PowhegHooksST: resonance veto scales taken from the POWHEG emission scales [emscales 1]\n";
136 std::cout <<
"PowhegHooksST: resonance veto scales reconstructed from the event record [emscales 0]\n";
154 if (event[iEmt].
id() == 21 || event[iRad].
id() != 21)
158 Vec4 pres(event[iRes].p());
159 Vec4 pemt(event[iEmt].p());
160 Vec4 prad(event[iRad].p());
163 double mRes = std::sqrt(pres * pres);
164 double Erad = prad * pres / mRes;
165 double Eemt = pemt * pres / mRes;
167 if ((event[iEmt].
id() != 21 && std::abs(event[iEmt].
id()) > 6)
168 || (event[iRad].
id() != 21 && std::abs(event[iRad].
id()) > 6)) {
169 if (loggerPtr) loggerPtr->ABORT_MSG(
"pTpowheg should be called only over QCD splittings");
174 if (std::abs(event[iEmt].
id()) != std::abs(event[iRad].
id())) {
175 scale = 2.0 * pemt * prad * Erad / Eemt;
178 scale = 2.0 * pemt * prad * Eemt * Erad / (std::pow(Eemt, 2) + std::pow(Erad, 2));
180 return std::sqrt(scale);
205 double veto_res_scale;
206 if (event[iRes].daughterList().
size() > 3) {
207 if (loggerPtr) loggerPtr->ABORT_MSG(
"A resonance can have at most 3 children");
213 veto_res_scale = 1e30;
216 if (std::abs(event[iRes].
id()) == 23 || std::abs(event[iRes].
id()) == 24) {
217 int iq = -1, iqb = -1, ig = -1;
218 for (
int i = 0; i < int(event[iRes].daughterList().
size()); i++) {
219 int iDau =
event[iRes].daughterList()[i];
220 if (event[iDau].
id() == 21) ig = iDau;
221 if (event[iDau].
id() > 0 && event[iDau].
id() < 6) iq = iDau;
222 if (event[iDau].
id() > -6 && event[iDau].
id() < 0) iqb = iDau;
226 if (iq == -1 && iqb == -1) {
227 veto_res_scale = 1e30;
234 double pTqbg = (iqb > 0) ?
pTpowhegFromRes(event, iqb, ig, iRes) : 1e30;
235 veto_res_scale = std::min(pTqg, pTqbg);
240 else if (std::abs(event[iRes].
id()) == 6) {
242 if (event[iRes].daughterList().
size() < 3) {
246 int iw = -1, ib = -1, ig = -1;
247 for (
int i = 0; i < int(event[iRes].daughterList().
size()); i++) {
248 int iDau =
event[iRes].daughterList()[i];
249 if (std::abs(event[iDau].
id()) == 24) iw = iDau;
250 if (std::abs(event[iDau].
id()) == 5) ib = iDau;
251 if (std::abs(event[iDau].
id()) == 21) ig = iDau;
253 if (iw < 0 || ib < 0 || ig < 0) {
254 if (loggerPtr) loggerPtr->ABORT_MSG(
"Top decay products not found");
261 veto_res_scale = 1e30;
264 return veto_res_scale;
298 for (
int i = 0; i <
event.size(); ++i) {
299 if (event[i].statusAbs() == 22 && !event[i].daughterList().
empty()) {
300 bool hasQCDDecay =
false;
301 for (
int d : event[i].daughterList()) {
302 if (particleDataPtr->colType(event[d].id()) != 0) hasQCDDecay =
true;
309 for (
int i = 0; i <
event.size(); ++i) {
310 if (event[i].status() == -22 && !event[i].daughterList().
empty()) {
334 if (iSys == 0 || !inResonance)
return PowhegHooks::doVetoFSREmission(sizeOld, e, iSys, inResonance);
339 const int iRad = e.size() - 2;
340 const int iEmtAft = e.size() - 3;
341 const int iEmtBef = e[iRad].mother1();
348 e[iEmtAft].colType() != 0 && e[iEmtBef].colType() != 0
349 && e[iRad].colType() != 0)) {
354 const int iRes = partonSystemsPtr->getInRes(iSys);
359 if (loggerPtr) loggerPtr->ABORT_MSG(
"Cannot find the resonance the showering is coming from");
362 const double pTmax = scale->second;
363 if (pTmax == 1e30)
return false;
367 return (pTcurr > pTmax);
411 std::vector<int> key;
414 for (
int i = iRes; i > 0; i =
event[i].mother1()) {
415 if (event[i].statusAbs() == 22) key.push_back(event[i].
id());
430 if (loggerPtr) loggerPtr->ABORT_MSG(
"Ambiguous resonance ancestry in POWHEG event");
446 if (!infoPtr)
return eventtype;
447 std::string comments = infoPtr->getEventComments();
448 if (comments.empty())
return eventtype;
450 std::istringstream iss(comments);
452 while (std::getline(iss, line)) {
453 if (line.compare(0, 5,
"#rwgt") == 0) {
454 std::istringstream lss(line.substr(5));
458 if (line.find(
"rad_type") != std::string::npos) {
460 if (std::sscanf(line.c_str(),
"# %d rad_type", &
type) == 1)
return type;
474 if (!infoPtr)
return;
475 std::string comments = infoPtr->getEventComments();
476 if (comments.empty())
return;
478 std::istringstream iss(comments);
480 while (std::getline(iss, line)) {
481 if (line.compare(0, 9,
"#emscales") != 0)
continue;
482 if (line.find(
"nemissions=") != std::string::npos)
continue;
486 if (std::sscanf(line.c_str(),
487 "#emscales i=%d scalup=%lf id_emitter=%d id_radiated=%d ires=%d",
504 if (es.ires == ires)
return es.scalup;
Pythia8_UserHooks::UserHooksFactory::Creator< Pythia8::PowhegHooksST > powhegSTCreator("PowhegST")
Pythia8_UserHooks::UserHooksFactory::Creator< Pythia8::PowhegHooksST > powhegHooksSTCreator("PowhegHooksST")
size_t size() const
Number of registered mappings.
static const Attributes_t empty
POWHEG resonance-veto hooks for single-top t- and s-channel events.
Pythia8_UserHooks::UserSetting< bool > m_debugSetting
std::vector< EmissionScale > m_readScales
PowhegHooksST()
Constructor and destructor for Athena UserHooksFactory.
bool initAfterBeams() override
Initialize settings for the POWHEG resonance-veto strategy.
bool doVetoProcessLevel(Event &event) override
Build resonance veto scales before showering starts.
double readScale(int ires, double fallback) const
Look up a POWHEG scale by original LHA resonance index.
int getEventType() const
Extract rad_type / eventtype from LHE event comments.
~PowhegHooksST() override
Pythia8_UserHooks::UserSetting< int > m_emscalesSetting
void storeResonanceScale(const std::vector< int > &key, double scale)
Store a scale for a resonance ancestry and reject ambiguity.
std::vector< int > resonanceKey(int iRes, const Event &event) const
Construct the stable signed-ID ancestry key for a resonance.
bool doVetoFSREmission(int sizeOld, const Event &e, int iSys, bool inResonance) override
Veto too-hard QCD radiation from a decayed resonance.
std::map< std::vector< int >, double > m_vetoResScale
double scaleResonance(int iRes, const Event &event) override
Reconstruct a resonance scale from the Pythia event record.
double pTpowhegFromRes(const Event &event, int iEmt, int iRad, int iRes)
Compute the POWHEG transverse scale of a resonance splitting.
bool canVetoProcessLevel() override
Advertise support for process-level processing.
Pythia8_UserHooks::UserSetting< int > m_emscalesAltSetting
void fillReadScales()
Populate POWHEG emission scales for the current event.
Pythia8_UserHooks::UserSetting< double > m_pTcutoffSetting
bool canSetResonanceScale() override
Disable Pythia's ordinary resonance-scale assignment.
Author: James Monk (jmonk@cern.ch).
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)