ATLAS Offline Software
Herwig7.cxx
Go to the documentation of this file.
1 // -*- C++ -*-
2 /*
3  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
4 */
5 
6 
12 #include "Herwig7_i/Herwig7.h"
13 
14 #include "ThePEG/Repository/EventGenerator.h"
15 #include "ThePEG/Repository/Repository.h"
16 #include "ThePEG/Persistency/PersistentIStream.h"
17 #include "ThePEG/Utilities/DynamicLoader.h"
18 #include "ThePEG/Utilities/Debug.h"
19 #include "ThePEG/EventRecord/Event.h"
20 #include "ThePEG/EventRecord/SubProcess.h"
21 #include "ThePEG/Handlers/XComb.h"
22 #include "ThePEG/Handlers/EventHandler.h"
23 #include "ThePEG/PDF/PartonExtractor.h"
24 #include "ThePEG/PDF/PDF.h"
25 
26 #include "Herwig/API/HerwigAPI.h"
27 
29 
30 #include "boost/thread/thread.hpp"
31 #include <filesystem>
32 #include "boost/algorithm/string.hpp"
33 
34 void convert_to_HepMC(const ThePEG::Event & m_event, HepMC::GenEvent & evt, bool nocopies,ThePEG::Energy eunit, ThePEG::Length lunit);
35 
36 
37 // Constructor
38 Herwig7::Herwig7(const std::string& name, ISvcLocator* pSvcLocator) :
39  GenModule(name, pSvcLocator),
40  m_use_seed_from_generatetf(false),
41  m_seed_from_generatetf(0),
42  m_pdfname_me("UNKNOWN"), m_pdfname_mpi("UNKNOWN") // m_pdfname_ps("UNKONWN"),
43 {
44  declareProperty("RunFile", m_runfile="Herwig7");
45  declareProperty("SetupFile", m_setupfile="");
46 
47  declareProperty("UseRandomSeedFromGeneratetf", m_use_seed_from_generatetf);
48  declareProperty("RandomSeedFromGeneratetf", m_seed_from_generatetf);
49 
50  declareProperty("PDFNameME", m_pdfname_me);
51  // declareProperty("PDFNamePS", m_pdfname_ps);
52  declareProperty("PDFNameMPI", m_pdfname_mpi);
53 
54  declareProperty("CrossSectionScaleFactor", m_xsscale=1.0);
55 
56  declareProperty("CleanupHerwigScratch", m_cleanup_herwig_scratch);
57 
58  declareProperty("Dsid", m_dsid);
59 }
60 
67  ATH_MSG_INFO("Herwig7 initialising...");
68 
70 
71  // Get random number seeds from Atlas RNG service, and pass them as Hw7 RNG
72  // default seeds (they can be overridden with an explicit Hw7 set command in the JO)
73  CLHEP::HepRandomEngine* engine = this->getRandomEngineDuringInitialize("Herwig7", m_randomSeed); // conditionsRun=1, lbn=1
74  const long* seeds = engine->getSeeds();
75  // The RNG service supplies two seeds, but Hw7 only uses one. To avoid the situation
76  // where varying one seed has no effect (this already stung us in pre-production
77  // job transform tests), we multiply the two seeds and let them wrap around the long
78  // type MAX_SIZE:
79  int32_t combined_seed = std::abs(seeds[0] * seeds[1]);
80  // Represent the combined seed as a string, so the config system can parse it back to a long ;)
81  std::ostringstream ss_seed;
82  ss_seed << combined_seed;
83  // Configure the API and print the seed to the log
85  ATH_MSG_INFO("Using the random number seed " + std::to_string(m_seed_from_generatetf) + " provided via Generate_tf.py");
87  } else {
88  ATH_MSG_INFO("Using the random number seed " + ss_seed.str() + " provided by athena");
89  m_api.seed(combined_seed);
90  }
91 
92  // Change repo log level and make sure that config errors result in a program exit
93  //ThePEG::Debug::level = 10000;
94  ThePEG::Repository::exitOnError() = 1;
95 
96  // Use everything from $DATAPATH and $LD_LIBRARY_PATH:
97  const char* datapath = getenv( "DATAPATH" );
98  std::vector< std::string > datapaths;
99  boost::split( datapaths, datapath,
100  boost::is_any_of( std::string( ":" ) ) );
101  for( const std::string& p : datapaths ) {
102  ThePEG::Repository::appendReadDir( p );
103  }
104  const char* ldpath = getenv( "LD_LIBRARY_PATH" );
105  std::vector< std::string > ldpaths;
106  boost::split( ldpaths, ldpath, boost::is_any_of( std::string( ":" ) ) );
107  for( const std::string& p : ldpaths ) {
108  ThePEG::DynamicLoader::appendPath( p );
109  }
110 
111  ATH_MSG_DEBUG("Num of library search paths = " << ThePEG::DynamicLoader::allPaths().size());
112 
113  // Use PathResolver to find default Hw7 ThePEG repository file.
114  const std::string repopath = PathResolver::find_file_from_list("HerwigDefaults.rpo", datapath);
115  ATH_MSG_DEBUG("Loading Herwig default repo from " << repopath);
116  ThePEG::Repository::load(repopath);
117  ATH_MSG_DEBUG("Successfully loaded Herwig default repository");
118 
119  ATH_MSG_INFO("Setting runfile name '"+m_runfile+"'");
121 
122  ATH_MSG_INFO("starting to prepare the run from runfile '"+m_runfile+"'...");
123 
124 #ifdef HEPMC3
125  m_runinfo = std::make_shared<HepMC3::GenRunInfo>();
127  struct HepMC3::GenRunInfo::ToolInfo generator={std::string("Herwig7"), std::string("7"), std::string("Used generator")};
128  m_runinfo->tools().push_back(generator);
129 #endif
130  // read in a Herwig runfile and obtain the event generator
131  m_gen = Herwig::API::prepareRun(m_api);
132  ATH_MSG_DEBUG("preparing the run...");
133 
134  return StatusCode::SUCCESS;
135 }
136 
137 
138 
143  ATH_MSG_DEBUG("Herwig7 generating an event");
144  assert(m_gen);
145  m_event = m_gen->shoot();
146  return StatusCode::SUCCESS;
147 }
148 
149 
150 
157 StatusCode Herwig7::fillEvt(HepMC::GenEvent* evt) {
158  // Convert the Herwig event into the HepMC GenEvent
159  ATH_MSG_DEBUG("Converting ThePEG::Event to HepMC::GenEvent");
160 #ifdef HEPMC3
161  if (!evt->run_info()) evt->set_run_info(m_runinfo);
162  evt->set_units(HepMC3::Units::MEV, HepMC3::Units::MM);
163 #endif
165  ATH_MSG_DEBUG("Converted ThePEG::Event to HepMC::GenEvent");
166 
167  // Fill the event number into HepMC event record
169  evt->set_event_number(evtInfo->eventNumber());
170 
171  // Fill event with random seeds from Atlas RNG service
172  const EventContext& ctx = Gaudi::Hive::currentContext();
173  const long* s = this->getRandomEngine("Herwig7", ctx)->getSeeds();
174  std::vector<long> seeds(s, s+2);
175  ATH_MSG_DEBUG("Random seeds: " << seeds[0] << ", " << seeds[1]);
177 
178  // Add a unit entry to the event weight vector if it's currently empty
179  if (evt->weights().empty()) {
180  evt->weights().push_back(m_event->weight());
181  }
182 
183  // Add PDF info manually (for now, until natively supported in the ThePEG converter)
184  ATH_MSG_DEBUG("Adding PDF info to HepMC");
185  // IDs of the partons going into the primary sub process
186  ThePEG::tSubProPtr sub = m_event->primarySubProcess();
187  int id1 = sub->incoming().first ->id();
188  int id2 = sub->incoming().second->id();
189  // Get the event handler
190  ThePEG::tcEHPtr eh = ThePEG::dynamic_ptr_cast<ThePEG::tcEHPtr>(m_event->handler());
191  // Get the values of x
192  double x1 = eh->lastX1();
193  double x2 = eh->lastX2();
194  // Get the pdfs
195  std::pair<ThePEG::PDF,ThePEG::PDF> pdfs;
196  pdfs.first = eh->pdf<ThePEG::PDF>(sub->incoming().first);
197  pdfs.second = eh->pdf<ThePEG::PDF>(sub->incoming().second);
198  // Get the scale
199  ThePEG::Energy2 scale = eh->lastScale();
200  double Q = std::sqrt(scale/ThePEG::GeV2);
201  // Get the values of the pdfs
202  double pdf1 = pdfs.first.xfx(sub->incoming().first ->dataPtr(), scale, x1);
203  double pdf2 = pdfs.first.xfx(sub->incoming().second->dataPtr(), scale, x2);
204  // Create the PDFinfo object
205 #ifdef HEPMC3
206  HepMC3::GenPdfInfoPtr pdfi = std::make_shared<HepMC3::GenPdfInfo>();
207  pdfi->set(id1, id2, x1, x2, Q, pdf1, pdf2);
208 #else
209  HepMC::PdfInfo pdfi(id1, id2, x1, x2, Q, pdf1, pdf2);
210 #endif
211  evt->set_pdf_info(pdfi);
212  ATH_MSG_DEBUG("Added PDF info to HepMC");
213 
214 //uncomment to list HepMC events
215 //#ifdef HEPMC3
216 // std::cout << " print::listing Herwig7 " << std::endl;
217 // HepMC3::Print::listing(std::cout, *evt);
218 //#else
219 // std::cout << " print::printing Herwig7 " << std::endl;
220 // evt->print();
221 //#endif
222 
223  return StatusCode::SUCCESS;
224 }
225 
226 
227 
232  ATH_MSG_INFO("Herwig7 finalizing.");
233  assert(m_gen);
234  ATH_MSG_INFO( "MetaData: generator = Herwig7 " << HWVERSION );
235  ATH_MSG_INFO( std::scientific << std::setprecision(5) << "MetaData: cross-section (nb) = " << m_gen->eventHandler()->integratedXSec()*m_xsscale/ThePEG::nanobarn);
236  // ATH_MSG_INFO( "MetaData: PDF = " << m_pdfname_me << " (ME); " << m_pdfname_ps << " (shower); " << m_pdfname_mpi << " (MPI)" );
237  ATH_MSG_INFO("MetaData: PDF = " << m_pdfname_me << " (ME); " << m_pdfname_mpi << " (shower/MPI)");
238  m_gen->finalize();
239  ThePEG::Repository::cleanup();
240 
241  // possibly tidy up working directory
242  if (m_cleanup_herwig_scratch && (std::filesystem::is_directory("Herwig-scratch") || std::filesystem::is_directory("Herwig-cache"))){
243 
244  ATH_MSG_INFO("removing Herwig-scratch/Herwig-cache folder from "+std::filesystem::current_path().string());
245 
246  // sleep for some time to allow all access to terminate
247  boost::this_thread::sleep(boost::posix_time::seconds(5));
248 
249  // in case the folder can't be deleted continue with warning
250  try {
251  (std::filesystem::remove_all("Herwig-scratch") || std::filesystem::remove_all("Herwig-cache"));
252  }
253  catch (const std::exception& e) {
254  ATH_MSG_WARNING("Failed to delete the folder 'Herwig-scratch': "+std::string(e.what()));
255  }
256 
257  }
258 
259  return StatusCode::SUCCESS;
260 }
261 
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
Powheg_tt_mtop_common.PDF
PDF
Definition: Powheg_tt_mtop_common.py:110
Herwig7API::inputfile
virtual std::string inputfile() const
Name of the file to be read.
Definition: Herwig7.h:52
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAOD::EventInfo_v1::eventNumber
uint64_t eventNumber() const
The current event's event number.
Herwig7::m_pdfname_mpi
std::string m_pdfname_mpi
PS PDF name, stored for AMI capture at finalize.
Definition: Herwig7.h:187
Herwig7::m_xsscale
double m_xsscale
Scale integrated cross section by a factor for MetaData output.
Definition: Herwig7.h:193
Herwig7::m_pdfname_me
std::string m_pdfname_me
ME PDF name, stored for AMI capture at finalize.
Definition: Herwig7.h:181
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
plotBeamSpotCompare.x2
x2
Definition: plotBeamSpotCompare.py:218
python.SystemOfUnits.MeV
int MeV
Definition: SystemOfUnits.py:154
JiveXML::Event
struct Event_t Event
Definition: ONCRPCServer.h:65
HepMC::GenPdfInfoPtr
HepMC::PdfInfo * GenPdfInfoPtr
Definition: PdfInfo.h:17
MM
@ MM
Definition: RegSelEnums.h:38
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
Herwig7::genFinalize
StatusCode genFinalize()
Close down the generator.
Definition: Herwig7.cxx:231
Herwig7::m_seed_from_generatetf
int m_seed_from_generatetf
Random number seed from Generate_tf.py.
Definition: Herwig7.h:178
Herwig7::genInitialize
StatusCode genInitialize()
Initialize the generator.
Definition: Herwig7.cxx:66
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
GenModule::getRandomEngine
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
Definition: GenModule.cxx:34
Herwig7::m_event
ThePEG::EventPtr m_event
ThePEG event object.
Definition: Herwig7.h:158
Herwig7::m_evtInfoKey
SG::ReadHandleKey< xAOD::EventInfo > m_evtInfoKey
Definition: Herwig7.h:198
Herwig7::m_dsid
int m_dsid
Gen_tf.py run args needed in interface.
Definition: Herwig7.h:196
GenModule
Base class for common behaviour of generator interfaces.
Definition: GenModule.h:39
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
python.SystemOfUnits.millimeter
int millimeter
Definition: SystemOfUnits.py:53
id2
HWIdentifier id2
Definition: LArRodBlockPhysicsV0.cxx:562
python.html.AtlRunQueryDQSummary.datapath
datapath
Definition: AtlRunQueryDQSummary.py:1205
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Herwig7.h
Athena interface for the Herwig7 generator.
calibdata.exception
exception
Definition: calibdata.py:496
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
python.LArCalib_HVCorrConfig.seconds
seconds
Definition: LArCalib_HVCorrConfig.py:98
Herwig7::m_api
Herwig7API m_api
Herwig7 API object.
Definition: Herwig7.h:152
Herwig7::Herwig7
Herwig7(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
Definition: Herwig7.cxx:38
PathResolver::find_file_from_list
static std::string find_file_from_list(const std::string &logical_file_name, const std::string &search_list, SearchType search_type=LocalSearch)
Definition: PathResolver.cxx:281
PathResolver.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
Herwig7::m_gen
ThePEG::EGPtr m_gen
ThePEG generator object.
Definition: Herwig7.h:155
mc.generator
generator
Configure Herwig7 These are the commands corresponding to what would go into the regular Herwig infil...
Definition: mc.MGH7_FxFx_H71-DEFAULT_test.py:18
SCT_ConditionsAlgorithms::CoveritySafe::getenv
std::string getenv(const std::string &variableName)
get an environment variable
Definition: SCT_ConditionsUtilities.cxx:17
Herwig7::m_runfile
std::string m_runfile
Name of run file.
Definition: Herwig7.h:168
Herwig7::callGenerator
StatusCode callGenerator()
Run the generator for one event.
Definition: Herwig7.cxx:142
python.SystemOfUnits.nanobarn
int nanobarn
Definition: SystemOfUnits.py:79
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
GenModule::m_randomSeed
IntegerProperty m_randomSeed
Seed for random number engine.
Definition: GenModule.h:84
Herwig7::fillEvt
StatusCode fillEvt(HepMC::GenEvent *evt)
Convert the generated event into the HepMC format.
Definition: Herwig7.cxx:157
python.root_pickle.load
def load(f, use_proxy=1, key=None)
Definition: root_pickle.py:476
Herwig7::m_use_seed_from_generatetf
bool m_use_seed_from_generatetf
Ignore random number seed provided by athena and use the one from Generate_tf.py instead.
Definition: Herwig7.h:175
Herwig7API::seed
virtual int seed() const
The number of events to generate.
Definition: Herwig7.h:74
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
convert_to_HepMC
void convert_to_HepMC(const ThePEG::Event &m_event, HepMC::GenEvent &evt, bool nocopies, ThePEG::Energy eunit, ThePEG::Length lunit)
Definition: Herwig7HepMC.cxx:140
Herwig7::m_setupfile
std::string m_setupfile
Name of setup file.
Definition: Herwig7.h:171
GenModule::getRandomEngineDuringInitialize
CLHEP::HepRandomEngine * getRandomEngineDuringInitialize(const std::string &streamName, unsigned long int randomSeedOffset, unsigned int conditionsRun=1, unsigned int lbn=1) const
Definition: GenModule.cxx:53
HepMC::set_random_states
void set_random_states(GenEvent *e, std::vector< T > a)
Definition: GenEvent.h:647
Herwig7::m_cleanup_herwig_scratch
bool m_cleanup_herwig_scratch
Possibly remove Herwig-scratch folder after finishing the event generation.
Definition: Herwig7.h:190