File indexing completed on 2026-10-15 08:24:44
0001 #include "PHHerwig7.h"
0002 #include "PHHerwig7Core.h"
0003 #include "PHHerwig7GenTrigger.h"
0004
0005 #include <phhepmc/PHGenIntegral.h>
0006 #include <phhepmc/PHGenIntegralv1.h>
0007 #include <phhepmc/PHHepMCGenHelper.h>
0008
0009 #include <fun4all/Fun4AllReturnCodes.h>
0010
0011 #include <phool/PHCompositeNode.h>
0012 #include <phool/PHIODataNode.h>
0013 #include <phool/PHNodeIterator.h>
0014 #include <phool/PHObject.h>
0015 #include <phool/PHRandomSeed.h>
0016 #include <phool/getClass.h>
0017 #include <phool/phool.h>
0018
0019
0020
0021 #include <HepMC/GenEvent.h>
0022 #include <HepMC/HepMCDefs.h>
0023 #include <HepMC/Units.h>
0024 #include <HepMC/WeightContainer.h>
0025 #include <ThePEG/Config/HepMCHelper.h>
0026 #include <ThePEG/Vectors/HepMCConverter.h>
0027
0028 #include <cassert>
0029 #include <cstdlib>
0030 #include <iostream>
0031
0032 PHHerwig7::PHHerwig7(const std::string &name)
0033 : SubsysReco(name)
0034 {
0035 PHHepMCGenHelper::set_embedding_id(1);
0036 }
0037
0038 int PHHerwig7::Init(PHCompositeNode *topNode)
0039 {
0040 if (m_RunFile.empty())
0041 {
0042 std::cout << PHWHERE << " no Herwig .run file set (PHHerwig7::set_run_file)" << std::endl;
0043 exit(EXIT_FAILURE);
0044 }
0045
0046 if (create_node_tree(topNode) != Fun4AllReturnCodes::EVENT_OK)
0047 {
0048 exit(EXIT_FAILURE);
0049 }
0050
0051 int seed = m_Seed;
0052 if (seed <= 0)
0053 {
0054 unsigned int s = PHRandomSeed();
0055
0056 seed = static_cast<int>(s % 2000000000U);
0057 if (seed <= 0)
0058 {
0059 seed = 1;
0060 }
0061 }
0062 std::cout << Name() << " Herwig random seed: " << seed << std::endl;
0063
0064 m_Core = std::make_unique<PHHerwig7Core>();
0065 m_Core->ui().m_RunFile = m_RunFile;
0066 m_Core->ui().m_SetupFile = m_SetupFile;
0067 m_Core->ui().m_Prepend = m_ReadDirs;
0068 m_Core->ui().m_Seed = seed;
0069
0070
0071 std::ios old_state(nullptr);
0072 old_state.copyfmt(std::cout);
0073 try
0074 {
0075 m_Core->init();
0076 }
0077 catch (const std::exception &e)
0078 {
0079 std::cout.copyfmt(old_state);
0080 std::cout << PHWHERE << " Herwig initialisation failed: " << e.what() << std::endl;
0081
0082
0083
0084 std::cout << PHWHERE << " Check the .run file and LHAPDF_DATA_PATH (hwrun.sh sets it to Source/lhapdf)" << std::endl;
0085 exit(EXIT_FAILURE);
0086 }
0087 std::cout.copyfmt(old_state);
0088
0089 if (Verbosity() > 0)
0090 {
0091 Print("CONFIG");
0092 }
0093 return Fun4AllReturnCodes::EVENT_OK;
0094 }
0095
0096 int PHHerwig7::process_event(PHCompositeNode * )
0097 {
0098 std::ios old_state(nullptr);
0099 old_state.copyfmt(std::cout);
0100
0101 HepMC::GenEvent *genevent = nullptr;
0102 long attempts = 0;
0103 while (!genevent)
0104 {
0105 ThePEG::EventPtr ev;
0106 try
0107 {
0108 ev = m_Core->next();
0109 }
0110 catch (const std::exception &e)
0111 {
0112 std::cout.copyfmt(old_state);
0113 std::cout << PHWHERE << " Herwig threw during event generation: " << e.what() << std::endl;
0114 return Fun4AllReturnCodes::ABORTRUN;
0115 }
0116 if (!ev)
0117 {
0118
0119
0120 std::cout.copyfmt(old_state);
0121 std::cout << PHWHERE << " Herwig returned no event after " << m_NGenerated
0122 << " generated (generator event limit reached?), aborting run" << std::endl;
0123 return Fun4AllReturnCodes::ABORTRUN;
0124 }
0125 ++m_NGenerated;
0126 const double w = ev->weight();
0127 m_SumWAll += w;
0128
0129 HepMC::GenEvent *cand = ThePEG::HepMCConverter<HepMC::GenEvent>::convert(
0130 *ev, false, ThePEG::Units::GeV, ThePEG::Units::millimeter);
0131 if (!cand)
0132 {
0133 std::cout << PHWHERE << " HepMC conversion failed" << std::endl;
0134 continue;
0135 }
0136 if (m_SaveEventWeightFlag && cand->weights().empty())
0137 {
0138 cand->weights().push_back(w);
0139 }
0140
0141
0142 bool passedTrigger = false;
0143 bool andScoreKeeper = true;
0144
0145 for (auto *trigger : m_RegisteredTriggers)
0146 {
0147 const bool trigResult = trigger->Apply(cand);
0148
0149 if (Verbosity() > 1)
0150 {
0151 std::cout << Name() << ": trigger " << trigger->GetName() << " pass = " << trigResult << std::endl;
0152 }
0153
0154 if (m_TriggersOR && trigResult)
0155 {
0156 passedTrigger = true;
0157 break;
0158 }
0159
0160 if (m_TriggersAND)
0161 {
0162 andScoreKeeper = andScoreKeeper && trigResult;
0163 }
0164 }
0165
0166 if ((andScoreKeeper && m_TriggersAND) || m_RegisteredTriggers.empty())
0167 {
0168 passedTrigger = true;
0169 }
0170
0171 if (passedTrigger)
0172 {
0173 genevent = cand;
0174 m_SumWPass += w;
0175 }
0176 else
0177 {
0178 delete cand;
0179 ++attempts;
0180 if (m_MaxAttempts > 0 && attempts >= m_MaxAttempts)
0181 {
0182 std::cout.copyfmt(old_state);
0183 std::cout << PHWHERE << " failed to pass trigger after " << attempts
0184 << " attempts, aborting run" << std::endl;
0185 return Fun4AllReturnCodes::ABORTRUN;
0186 }
0187 }
0188 }
0189
0190 PHHepMCGenEvent *success = PHHepMCGenHelper::insert_event(genevent);
0191 if (!success)
0192 {
0193 std::cout.copyfmt(old_state);
0194 std::cout << PHWHERE << " failed to add event to the HepMC record" << std::endl;
0195 return Fun4AllReturnCodes::ABORTRUN;
0196 }
0197 ++m_NPassed;
0198
0199 if (m_IntegralNode)
0200 {
0201 const double sigma_pb = m_Core->xsec_pb();
0202 m_IntegralNode->set_N_Generator_Accepted_Event(m_NGenerated);
0203 m_IntegralNode->set_N_Processed_Event(m_NPassed);
0204 m_IntegralNode->set_Sum_Of_Weight(m_SumWAll);
0205
0206 m_IntegralNode->set_Integrated_Lumi(sigma_pb > 0 ? double(m_NGenerated) / sigma_pb : 0.0);
0207 }
0208
0209 std::cout.copyfmt(old_state);
0210 return Fun4AllReturnCodes::EVENT_OK;
0211 }
0212
0213 int PHHerwig7::End(PHCompositeNode * )
0214 {
0215 std::ios old_state(nullptr);
0216 old_state.copyfmt(std::cout);
0217 if (m_Core)
0218 {
0219 m_Core->finish();
0220 }
0221 std::cout.copyfmt(old_state);
0222
0223 std::cout << Name() << ": generated " << m_NGenerated << ", passed trigger " << m_NPassed
0224 << " (eff " << (m_NGenerated ? double(m_NPassed) / double(m_NGenerated) : 0.0) << ")"
0225 << ", sumW all=" << m_SumWAll << " passed=" << m_SumWPass
0226 << ", sigma=" << (m_Core ? m_Core->xsec_pb() : 0.0) << " +- "
0227 << (m_Core ? m_Core->xsec_err_pb() : 0.0) << " pb" << std::endl;
0228 if (m_IntegralNode && Verbosity() > 0)
0229 {
0230 m_IntegralNode->identify();
0231 }
0232 return Fun4AllReturnCodes::EVENT_OK;
0233 }
0234
0235 int PHHerwig7::create_node_tree(PHCompositeNode *topNode)
0236 {
0237 PHHepMCGenHelper::create_node_tree(topNode);
0238
0239 PHNodeIterator iter(topNode);
0240 PHCompositeNode *sumNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
0241 if (!sumNode)
0242 {
0243 std::cout << PHWHERE << " RUN node missing, doing nothing" << std::endl;
0244 return Fun4AllReturnCodes::ABORTRUN;
0245 }
0246 if (m_SaveIntegratedLuminosityFlag)
0247 {
0248 m_IntegralNode = findNode::getClass<PHGenIntegral>(sumNode, "PHGenIntegral");
0249 if (!m_IntegralNode)
0250 {
0251 m_IntegralNode = new PHGenIntegralv1("PHHerwig7 with embedding ID of " + std::to_string(PHHepMCGenHelper::get_embedding_id()));
0252 PHIODataNode<PHObject> *newnode = new PHIODataNode<PHObject>(m_IntegralNode, "PHGenIntegral", "PHObject");
0253 sumNode->addNode(newnode);
0254 }
0255 else
0256 {
0257 std::cout << PHWHERE << " RUN/PHGenIntegral already exists; refusing to overwrite. "
0258 << "Call PHHerwig7::save_integrated_luminosity(false) if that is intended." << std::endl;
0259 return Fun4AllReturnCodes::ABORTRUN;
0260 }
0261 }
0262 return Fun4AllReturnCodes::EVENT_OK;
0263 }
0264
0265 void PHHerwig7::Print(const std::string & ) const
0266 {
0267 std::cout << Name() << " configuration:" << std::endl
0268 << " run file : " << m_RunFile << std::endl
0269 << " setup file : " << (m_SetupFile.empty() ? "(none)" : m_SetupFile) << std::endl
0270 << " embedding id : " << PHHepMCGenHelper::get_embedding_id() << std::endl
0271 << " triggers : " << m_RegisteredTriggers.size() << std::endl
0272 << " combine : " << (m_TriggersAND ? "AND" : "OR") << std::endl;
0273
0274 for (auto *trigger : m_RegisteredTriggers)
0275 {
0276 std::cout << " trigger : " << trigger->GetName() << std::endl;
0277 }
0278 }
0279
0280
0281 void PHHerwig7::register_trigger(PHHerwig7GenTrigger *trigger)
0282 {
0283 if (Verbosity() > 0)
0284 {
0285 std::cout << Name() << ": trigger " << trigger->GetName() << " registered" << std::endl;
0286 }
0287
0288 m_RegisteredTriggers.push_back(trigger);
0289 }