ATLAS Offline Software
Herwig7.cxx
Go to the documentation of this file.
1 // -*- C++ -*-
2 /*
3  Copyright (C) 2002-2022 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  // Horrid runtime ATLAS env variable and CMT path mangling to work out ThePEG module search paths
97  char* env1 = getenv("CMTPATH");
98  char* env2 = getenv("CMTCONFIG");
99  std::string reposearchpaths;
100  if (env1 == nullptr || env2 == nullptr) {
101  // Use everything from $DATAPATH and $LD_LIBRARY_PATH:
102  const char* datapath = getenv( "DATAPATH" );
103  reposearchpaths = datapath;
104  std::vector< std::string > datapaths;
105  boost::split( datapaths, datapath,
106  boost::is_any_of( std::string( ":" ) ) );
107  for( const std::string& p : datapaths ) {
108  ThePEG::Repository::appendReadDir( p );
109  }
110  const char* ldpath = getenv( "LD_LIBRARY_PATH" );
111  std::vector< std::string > ldpaths;
112  boost::split( ldpaths, ldpath, boost::is_any_of( std::string( ":" ) ) );
113  for( const std::string& p : ldpaths ) {
114  ThePEG::DynamicLoader::appendPath( p );
115  }
116  } else {
117  std::vector<std::string> cmtpaths;
118  boost::split(cmtpaths, env1, boost::is_any_of(std::string(":")));
119  const std::string cmtconfig = env2;
120  const std::string sharepath = "/InstallArea/" + cmtconfig + "/share";
121  const std::string libpath = "/InstallArea/" + cmtconfig + "/lib";
122  // Prepend to the repository and loader command file search paths
123  for(const std::string& p: cmtpaths) {
124  const std::string cmtsharepath = p + sharepath;
125  ATH_MSG_DEBUG("Appending " + cmtsharepath + " to ThePEG repository and command file search paths");
126  reposearchpaths = reposearchpaths + (reposearchpaths.length() == 0 ? "" : ":") + cmtsharepath;
127  ThePEG::Repository::appendReadDir(cmtsharepath);
128  const std::string cmtlibpath = p + libpath;
129  ATH_MSG_DEBUG("Appending " + cmtlibpath + " to ThePEG loader search path");
130  ThePEG::DynamicLoader::appendPath(cmtlibpath);
131  }
132  }
133  ATH_MSG_DEBUG("Num of library search paths = " << ThePEG::DynamicLoader::allPaths().size());
134 
135  // Use PathResolver to find default Hw7 ThePEG repository file.
136  const std::string repopath = PathResolver::find_file_from_list("HerwigDefaults.rpo", reposearchpaths);
137  ATH_MSG_DEBUG("Loading Herwig default repo from " << repopath);
138  ThePEG::Repository::load(repopath);
139  ATH_MSG_DEBUG("Successfully loaded Herwig default repository");
140 
141  ATH_MSG_INFO("Setting runfile name '"+m_runfile+"'");
143 
144  ATH_MSG_INFO("starting to prepare the run from runfile '"+m_runfile+"'...");
145 
146 #ifdef HEPMC3
147  m_runinfo = std::make_shared<HepMC3::GenRunInfo>();
149  struct HepMC3::GenRunInfo::ToolInfo generator={std::string("Herwig7"), std::string("7"), std::string("Used generator")};
150  m_runinfo->tools().push_back(generator);
151 #endif
152  // read in a Herwig runfile and obtain the event generator
153  m_gen = Herwig::API::prepareRun(m_api);
154  ATH_MSG_DEBUG("preparing the run...");
155 
156  return StatusCode::SUCCESS;
157 }
158 
159 
160 
165  ATH_MSG_DEBUG("Herwig7 generating an event");
166  assert(m_gen);
167  m_event = m_gen->shoot();
168  return StatusCode::SUCCESS;
169 }
170 
171 
172 
179 StatusCode Herwig7::fillEvt(HepMC::GenEvent* evt) {
180  // Convert the Herwig event into the HepMC GenEvent
181  ATH_MSG_DEBUG("Converting ThePEG::Event to HepMC::GenEvent");
182 #ifdef HEPMC3
183  if (!evt->run_info()) evt->set_run_info(m_runinfo);
184  evt->set_units(HepMC3::Units::MEV, HepMC3::Units::MM);
185 #endif
187  ATH_MSG_DEBUG("Converted ThePEG::Event to HepMC::GenEvent");
188 
189  // Fill the event number into HepMC event record
191  evt->set_event_number(evtInfo->eventNumber());
192 
193  // Fill event with random seeds from Atlas RNG service
194  const EventContext& ctx = Gaudi::Hive::currentContext();
195  const long* s = this->getRandomEngine("Herwig7", ctx)->getSeeds();
196  std::vector<long> seeds(s, s+2);
197  ATH_MSG_DEBUG("Random seeds: " << seeds[0] << ", " << seeds[1]);
199 
200  // Add a unit entry to the event weight vector if it's currently empty
201  if (evt->weights().empty()) {
202  evt->weights().push_back(m_event->weight());
203  }
204 
205  // Add PDF info manually (for now, until natively supported in the ThePEG converter)
206  ATH_MSG_DEBUG("Adding PDF info to HepMC");
207  // IDs of the partons going into the primary sub process
208  ThePEG::tSubProPtr sub = m_event->primarySubProcess();
209  int id1 = sub->incoming().first ->id();
210  int id2 = sub->incoming().second->id();
211  // Get the event handler
212  ThePEG::tcEHPtr eh = ThePEG::dynamic_ptr_cast<ThePEG::tcEHPtr>(m_event->handler());
213  // Get the values of x
214  double x1 = eh->lastX1();
215  double x2 = eh->lastX2();
216  // Get the pdfs
217  std::pair<ThePEG::PDF,ThePEG::PDF> pdfs;
218  pdfs.first = eh->pdf<ThePEG::PDF>(sub->incoming().first);
219  pdfs.second = eh->pdf<ThePEG::PDF>(sub->incoming().second);
220  // Get the scale
221  ThePEG::Energy2 scale = eh->lastScale();
222  double Q = std::sqrt(scale/ThePEG::GeV2);
223  // Get the values of the pdfs
224  double pdf1 = pdfs.first.xfx(sub->incoming().first ->dataPtr(), scale, x1);
225  double pdf2 = pdfs.first.xfx(sub->incoming().second->dataPtr(), scale, x2);
226  // Create the PDFinfo object
227 #ifdef HEPMC3
228  HepMC3::GenPdfInfoPtr pdfi = std::make_shared<HepMC3::GenPdfInfo>();
229  pdfi->set(id1, id2, x1, x2, Q, pdf1, pdf2);
230 #else
231  HepMC::PdfInfo pdfi(id1, id2, x1, x2, Q, pdf1, pdf2);
232 #endif
233  evt->set_pdf_info(pdfi);
234  ATH_MSG_DEBUG("Added PDF info to HepMC");
235 
236 //uncomment to list HepMC events
237 //#ifdef HEPMC3
238 // std::cout << " print::listing Herwig7 " << std::endl;
239 // HepMC3::Print::listing(std::cout, *evt);
240 //#else
241 // std::cout << " print::printing Herwig7 " << std::endl;
242 // evt->print();
243 //#endif
244 
245  return StatusCode::SUCCESS;
246 }
247 
248 
249 
254  ATH_MSG_INFO("Herwig7 finalizing.");
255  assert(m_gen);
256  ATH_MSG_INFO( "MetaData: generator = Herwig7 " << HWVERSION );
257  ATH_MSG_INFO( std::scientific << std::setprecision(5) << "MetaData: cross-section (nb) = " << m_gen->eventHandler()->integratedXSec()*m_xsscale/ThePEG::nanobarn);
258  // ATH_MSG_INFO( "MetaData: PDF = " << m_pdfname_me << " (ME); " << m_pdfname_ps << " (shower); " << m_pdfname_mpi << " (MPI)" );
259  ATH_MSG_INFO("MetaData: PDF = " << m_pdfname_me << " (ME); " << m_pdfname_mpi << " (shower/MPI)");
260  m_gen->finalize();
261  ThePEG::Repository::cleanup();
262 
263  // possibly tidy up working directory
264  if (m_cleanup_herwig_scratch && (std::filesystem::is_directory("Herwig-scratch") || std::filesystem::is_directory("Herwig-cache"))){
265 
266  ATH_MSG_INFO("removing Herwig-scratch/Herwig-cache folder from "+std::filesystem::current_path().string());
267 
268  // sleep for some time to allow all access to terminate
269  boost::this_thread::sleep(boost::posix_time::seconds(5));
270 
271  // in case the folder can't be deleted continue with warning
272  try {
273  (std::filesystem::remove_all("Herwig-scratch") || std::filesystem::remove_all("Herwig-cache"));
274  }
275  catch (const std::exception& e) {
276  ATH_MSG_WARNING("Failed to delete the folder 'Herwig-scratch': "+std::string(e.what()));
277  }
278 
279  }
280 
281  return StatusCode::SUCCESS;
282 }
283 
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
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
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:191
Herwig7::m_xsscale
double m_xsscale
Scale integrated cross section by a factor for MetaData output.
Definition: Herwig7.h:197
Herwig7::m_pdfname_me
std::string m_pdfname_me
ME PDF name, stored for AMI capture at finalize.
Definition: Herwig7.h:185
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
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:253
Herwig7::m_seed_from_generatetf
int m_seed_from_generatetf
Random number seed from Generate_tf.py.
Definition: Herwig7.h:182
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:162
Herwig7::m_evtInfoKey
SG::ReadHandleKey< xAOD::EventInfo > m_evtInfoKey
Definition: Herwig7.h:202
Herwig7::m_dsid
int m_dsid
Gen_tf.py run args needed in interface.
Definition: Herwig7.h:200
GenModule
Base class for common behaviour of generator interfaces.
Definition: GenModule.h:39
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
python.SystemOfUnits.millimeter
int millimeter
Definition: SystemOfUnits.py:53
id2
HWIdentifier id2
Definition: LArRodBlockPhysicsV0.cxx:564
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:86
Herwig7::m_api
Herwig7API m_api
Herwig7 API object.
Definition: Herwig7.h:156
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:195
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:159
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
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
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:172
Herwig7::callGenerator
StatusCode callGenerator()
Run the generator for one event.
Definition: Herwig7.cxx:164
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:179
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:179
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:175
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:525
Herwig7::m_cleanup_herwig_scratch
bool m_cleanup_herwig_scratch
Possibly remove Herwig-scratch folder after finishing the event generation.
Definition: Herwig7.h:194