ATLAS Offline Software
Pythia8_i.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 #include "Pythia8_i/Pythia8_i.h"
8 
10 #include <boost/algorithm/string.hpp>
11 #include <boost/lexical_cast.hpp>
12 
13 // calls to fortran routines
16 
17 #include <sstream>
18 // For limits
19 #include <limits>
20 
21 
22 namespace {
23  // Name of random number stream
24  std::string s_pythia_stream{"PYTHIA8_INIT"};
25 }
26 
27 
28 // fix Pythia8 shower weights change in conventions
29 #define PYTHIA8_NWEIGHTS nWeights
30 #define PYTHIA8_WEIGHT weight
31 #define PYTHIA8_WLABEL weightLabel
32 #define PYTHIA8_CONVERSION 1.0
33 
34 #ifdef PYTHIA_VERSION_INTEGER
35  #undef PYTHIA8_NWEIGHTS
36  #undef PYTHIA8_WEIGHT
37  #undef PYTHIA8_WLABEL
38  #if PYTHIA_VERSION_INTEGER > 8303
39  #define PYTHIA8_NWEIGHTS nWeightGroups
40  #else
41  #define PYTHIA8_NWEIGHTS nVariationGroups
42  #endif
43  #define PYTHIA8_WEIGHT getGroupWeight
44  #define PYTHIA8_WLABEL getGroupName
45 #endif
46 
51 namespace {
52 
53 std::string py8version()
54 {
55  static const std::string incdir (PY8INCLUDE_DIR);
56  std::string::size_type pos = incdir.find ("/pythia8/");
57  if (pos == std::string::npos) return "";
58  pos += 9;
59  std::string::size_type pos2 = incdir.find ("/", pos);
60  if (pos2 == std::string::npos) pos2 = incdir.size();
61  return incdir.substr (pos, pos2-pos);
62 }
63 
64 
65 }
66 
68 Pythia8_i::Pythia8_i(const std::string &name, ISvcLocator *pSvcLocator)
69 : GenModule(name, pSvcLocator)
70 {
71  m_particleIDs["PROTON"] = PROTON;
72  m_particleIDs["ANTIPROTON"] = ANTIPROTON;
73  m_particleIDs["ELECTRON"] = ELECTRON;
74  m_particleIDs["POSITRON"] = POSITRON;
75  m_particleIDs["NEUTRON"] = NEUTRON;
76  m_particleIDs["ANTINEUTRON"] = ANTINEUTRON;
77  m_particleIDs["MUON"] = MUON;
78  m_particleIDs["ANTIMUON"] = ANTIMUON;
79  m_particleIDs["LEAD"] = LEAD;
80 
81 }
82 
85 
86  #ifndef PYTHIA8_3SERIES
87 // if(m_userHookPtr != 0) delete m_userHookPtr;
88 
89 // for(UserHooksPtrType ptr: m_userHooksPtrs){
90 // delete ptr;
91 // }
92  #endif
93 }
94 
97 
98  ATH_MSG_DEBUG("Pythia8_i from genInitialize()");
99 
100  ATH_MSG_INFO("XML Path is " + xmlpath());
101  m_pythia = std::make_unique<Pythia8::Pythia> (xmlpath());
102 #ifdef HEPMC3
103  m_runinfo = std::make_shared<HepMC3::GenRunInfo>();
105  struct HepMC3::GenRunInfo::ToolInfo generator={std::string("Pythia8"),py8version(),std::string("Used generator")};
106  m_runinfo->tools().push_back(generator);
107 #endif
108 
109  bool canInit = true;
110 
111  m_version = m_pythia->settings.parm("Pythia:versionNumber");
112 
113  s_pythia_stream = "PYTHIA8_INIT";
114 
115  // By default add "nominal" to the list of shower weight names
117  m_showerWeightNames.insert(m_showerWeightNames.begin(), "nominal");
118 
119  // We do explicitly set tune 4C, since it is the starting point for many other tunes
120  // Tune 4C for pp collisions
121  m_pythia->readString("Tune:pp = 5");
122 
123  // also use CTEQ6L1 from LHAPDF 6 by default
124  // can be over-written using JO
125  m_pythia->readString("PDF:pSet= LHAPDF6:cteq6l1");
126 
127  // switch off verbose event print out
128  m_pythia->readString("Next:numberShowEvent = 0");
129 
130  // Add flag to switch off from JO the Pythia8ToHepMC::print_inconsistency internal variable
131  m_pythia->settings.addFlag("AthenaPythia8ToHepMC:print_inconsistency",true);
132 
133  // Add UserHooks first because these potentially add new settings that must exist prior to parsing commands
134 
135  for(const auto &hook: m_userHooks){
136  ATH_MSG_INFO("Adding user hook " + hook + ".");
137  bool canSetHook = true;
138  if (hook == "SuppressSmallPT") {
140  canSetHook=m_pythia->setUserHooksPtr(PYTHIA8_PTRWRAP(m_SuppressSmallPT));
141 }
142  else {
144  canSetHook = m_pythia->addUserHooksPtr(m_userHooksPtrs.back());
145 }
146  if(!canSetHook){
147  ATH_MSG_ERROR("Unable to set requested user hook.");
148  ATH_MSG_ERROR("Pythia 8 initialisation will FAIL!");
149  canInit=false;
150  }
151  }
152 
153  for(const std::pair<const std::string, double> &param : Pythia8_UserHooks::UserHooksFactory::userSettings<double>()){
154  m_pythia->settings.addParm(param.first, param.second, false, false, 0., 0.);
155  }
156 
157  for(const std::pair<const std::string, int> &param : Pythia8_UserHooks::UserHooksFactory::userSettings<int>()){
158  m_pythia->settings.addMode(param.first, param.second, false, false, 0., 0.);
159  }
160 
161  for(const std::pair<const std::string, bool> &param : Pythia8_UserHooks::UserHooksFactory::userSettings<bool>()){
162  m_pythia->settings.addFlag(param.first, param.second);
163  }
164 
165  for(const std::pair<const std::string, std::string> &param : Pythia8_UserHooks::UserHooksFactory::userSettings<std::string>()){
166  m_pythia->settings.addWord(param.first, param.second);
167  }
168 
169  if( ! m_athenaTool.empty() ){
170  if(m_athenaTool.retrieve().isFailure()){
171  ATH_MSG_ERROR("Unable to retrieve Athena Tool for custom Pythia processing");
172  return StatusCode::FAILURE;
173  }
174  else {
175  StatusCode status = m_athenaTool->InitializePythiaInfo(*m_pythia);
176  if(status != StatusCode::SUCCESS) return status;
177  }
178  }
179 
180  // Now apply the settings from the JO
181  for(const std::string &cmd : m_commands){
182 
183  if(cmd.compare("")==0) continue;
184  else if (cmd.find("Beams:id") != std::string::npos ) {
185  ATH_MSG_ERROR("With command '" << cmd << "' you are trying to set a beam different from p: please use the Beam1/Beam2 properties instead:");
186  ATH_MSG_ERROR(" example: genSeq.Pythia8.Beam1 = 'LEAD'");
187  ATH_MSG_ERROR(" genSeq.Pythia8.Beam2 = 'ANTINEUTRON'");
188  return StatusCode::FAILURE;
189  }
190  else if (cmd.find("Beams:frameType") != std::string::npos ) {
192  ATH_MSG_WARNING(" Found an explicit 'Beams:frameType' command: this will override transform beams momenta/energy parameters, regardless of its requested value. ");
193  }
194 
195  bool read = m_pythia->readString(cmd);
196 
197  if(!read){
198  ATH_MSG_ERROR("Pythia could not understand the command '"<< cmd<<"'");
199  return StatusCode::FAILURE;
200  }
201  }
202 
205 
206  ATH_MSG_INFO("Beam1 = "<<beam1);
207  ATH_MSG_INFO("Beam2 = "<<beam2);
208 
209  if(beam1 == 0 || beam2 == 0){
210  ATH_MSG_ERROR("Invalid beam particle!");
211  return StatusCode::FAILURE;
212  }
213 
214 
215 
216  if(m_useRndmGenSvc){
217 
218  ATH_MSG_INFO(" !!!!!!!!!!!! WARNING ON PYTHIA RANDOM NUMBERS !!!!!!!!!! ");
219  ATH_MSG_INFO(" THE ATHENA SERVICE AthRNGenSvc IS USED.");
220  ATH_MSG_INFO(" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ");
221 
222  m_atlasRndmEngine = std::make_shared<customRndm>();
223 
224  CLHEP::HepRandomEngine* rndmEngine = getRandomEngineDuringInitialize(s_pythia_stream, m_randomSeed, m_dsid); // NOT THREAD-SAFE
225  m_atlasRndmEngine->init(rndmEngine);
226 #if PYTHIA_VERSION_INTEGER >= 8310
227  m_pythia->setRndmEnginePtr(m_atlasRndmEngine);
228 #else
229  m_pythia->setRndmEnginePtr(m_atlasRndmEngine.get());
230 #endif
231  s_pythia_stream = "PYTHIA8";
232  }else{
233  ATH_MSG_INFO(" !!!!!!!!!!!! WARNING ON PYTHIA RANDOM NUMBERS !!!!!!!!!! ");
234  ATH_MSG_INFO(" THE STANDARD PYTHIA8 RANDOM NUMBER SERVICE IS USED.");
235  ATH_MSG_INFO(" THE ATHENA SERVICE AthRNGSvc IS ***NOT*** USED.");
236  ATH_MSG_INFO(" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ");
237  }
238 
239  if(m_userProcess != ""){
241  }
242 
243 
244 
245  if(m_userResonances.value() != ""){
246 
247  std::vector<std::string> resonanceArgs;
248 
249  boost::split(resonanceArgs, m_userResonances.value(), boost::is_any_of(":"));
250  if(resonanceArgs.size() != 2){
251  ATH_MSG_ERROR("Cannot Understand UserResonance job option!");
252  ATH_MSG_ERROR("You should specify it as a 'name:id1,id2,id3...'");
253  ATH_MSG_ERROR("Where name is the name of your UserResonance, and id1,id2,id3 are a comma separated list of PDG IDs to which it is applied");
254  canInit = false;
255  }
256  std::vector<std::string> resonanceIds;
257  boost::split(resonanceIds, resonanceArgs.back(), boost::is_any_of(","));
258  if(resonanceIds.size()==0){
259  ATH_MSG_ERROR("You did not specifiy any PDG ids to which your user resonance width should be applied!");
260  ATH_MSG_ERROR("You should specify a list as 'name:id1,id2,id3...'");
261  ATH_MSG_ERROR("Where name is the name of your UserResonance, and id1,id2,id3 are a comma separated list of PDG IDs to which it is applied");
262  canInit=false;
263  }
264 
265  for(std::vector<std::string>::const_iterator sId = resonanceIds.begin();
266  sId != resonanceIds.end(); ++sId){
267  int idResIn = boost::lexical_cast<int>(*sId);
268  m_userResonancePtrs.push_back(Pythia8_UserResonance::UserResonanceFactory::create(resonanceArgs.front(), idResIn));
269  }
270 
271  for(std::shared_ptr<Pythia8::ResonanceWidths>& resonance : m_userResonancePtrs) {
272 #if PYTHIA_VERSION_INTEGER >= 8310
273  m_pythia->setResonancePtr(resonance);
274 #else
275  m_pythia->setResonancePtr(resonance.get());
276 #endif
277  }
278 
279  }
280 
281  if(m_particleDataFile != "") {
282  if(!m_pythia->particleData.reInit(m_particleDataFile, true)){
283  ATH_MSG_ERROR("Unable to read requested particle data table: " + m_particleDataFile + " !!");
284  ATH_MSG_ERROR("Pythia 8 initialisation will FAIL!");
285  canInit = false;
286  }
287  }
288 
289  if(m_lheFile != ""){
290  if(m_procPtr){
291  ATH_MSG_ERROR("Both LHE file and user process have been specified");
292  ATH_MSG_ERROR("LHE input does not make sense with a user process!");
293  canInit = false;
294  }
295 
296  canInit = canInit && m_pythia->readString("Beams:frameType = 4");
297  canInit = canInit && m_pythia->readString("Beams:LHEF = " + m_lheFile);
298  if(!canInit){
299  ATH_MSG_ERROR("Unable to read requested LHE file: " + m_lheFile + " !");
300  ATH_MSG_ERROR("Pythia 8 initialisation will FAIL!");
301  }
302  }else{
304  canInit = canInit && m_pythia->readString("Beams:frameType = 1");
305  canInit = canInit && m_pythia->readString("Beams:eCM = " + std::to_string(m_collisionEnergy));
306  }
307  canInit = canInit && m_pythia->readString("Beams:idA = " + std::to_string(beam1));
308  canInit = canInit && m_pythia->readString("Beams:idB = " + std::to_string(beam2));
309  }
310 
311  if(m_procPtr){
312 #if PYTHIA_VERSION_INTEGER >= 8310
313  if(!m_pythia->setSigmaPtr(m_procPtr))
314 #else
315  if(!m_pythia->setSigmaPtr(m_procPtr.get()))
316 #endif
317  {
318  ATH_MSG_ERROR("Unable to set requested user process: " + m_userProcess + " !!");
319  ATH_MSG_ERROR("Pythia 8 initialisation will FAIL!");
320  canInit = false;
321  }
322  }
323 
324  StatusCode returnCode = StatusCode::SUCCESS;
325 
326  m_pythia->particleData.listXML(m_outputParticleDataFile.value().substr(0,m_outputParticleDataFile.value().find("xml"))+"orig.xml");
327  m_pythia->settings.writeFile("Settings_before.log",true);
328 
329  if(canInit){
330  canInit = m_pythia->init();
331  }
332 
333  if(!canInit){
334  returnCode = StatusCode::FAILURE;
335  ATH_MSG_ERROR(" *** Unable to initialise Pythia !! ***");
336  }
337 
338  m_pythia->particleData.listXML(m_outputParticleDataFile);
339  m_pythia->settings.writeFile("Settings_after.log",true);
340 
341  //counter for event failures;
342  m_failureCount = 0;
343 
345 
346  // Set set_print_inconsistency to Athena corresponding flag (allowing to change it from JO)
347  m_pythiaToHepMC.set_print_inconsistency( m_pythia->settings.flag("AthenaPythia8ToHepMC:print_inconsistency") );
348 
349  m_pythiaToHepMC.set_store_pdf(true);
350  m_pythiaToHepMC.set_store_weights(false);
351 
352  return returnCode;
353 }
354 
357 
358  ATH_MSG_DEBUG(">>> Pythia8_i from callGenerator");
359 
360  if(m_useRndmGenSvc){
361  //Re-seed the random number stream
362  long seeds[7];
363  const EventContext& ctx = Gaudi::Hive::currentContext();
364  ATHRNG::calculateSeedsMC21(seeds, s_pythia_stream, ctx.eventID().event_number(), m_dsid, m_randomSeed);
365  m_atlasRndmEngine->getEngine()->setSeeds(seeds, 0); // NOT THREAD-SAFE
366  m_seeds.clear();
367  m_seeds.push_back(seeds[0]);
368  m_seeds.push_back(seeds[1]);
369  }
370 
371  bool status = m_pythia->next();
372 
373  StatusCode returnCode = StatusCode::SUCCESS;
374 
375  if(!status){
376  ++m_failureCount;
378  ATH_MSG_ERROR("Exceeded the max number of consecutive event failures.");
379  returnCode = StatusCode::FAILURE;
380  }else{
381  ATH_MSG_INFO("Event generation failed - re-trying.");
382  returnCode = this->callGenerator();
383  }
384  }
385 
386  ATH_MSG_DEBUG("Now checking with Tool.empty() second time");
387  if( ! m_athenaTool.empty() ){
388  StatusCode stat = m_athenaTool->ModifyPythiaEvent(*m_pythia);
389  if(stat != StatusCode::SUCCESS) returnCode = stat;
390  }
391 
392  m_failureCount = 0;
393 
394  m_nAccepted += 1.;
395  // some CKKWL merged events have zero weight (or unfilled event).
396  // start again with such events
397 
398  double eventWeight = m_pythia->info.mergingWeight()*m_pythia->info.weight();
399 
400 
401  if(returnCode != StatusCode::FAILURE &&
402  // Here this is a double, but it may be converted into float at some point downstream
403  (std::abs(eventWeight) < std::numeric_limits<float>::min() ||
404  m_pythia->event.size() < 2)){
405 
406  returnCode = this->callGenerator();
407  } else if ( std::abs(eventWeight) < std::numeric_limits<float>::min() &&
408  std::abs(eventWeight) > std::numeric_limits<double>::min() ){
409  ATH_MSG_WARNING("Found event weight " << eventWeight << " between the float and double precision limits. Rejecting event.");
410  } else {
411  m_nMerged += eventWeight;
413 
414  // For FxFx cross section:
415  m_sigmaTotal+=m_pythia->info.weight();
416  }
417 
418  return returnCode;
419 }
420 
423 
424  ATH_MSG_DEBUG(">>> Pythia8_i from fillEvt");
425 
426  evt->set_event_number(m_internal_event_number);
427 
428  // if using "getGroupWeight" and | lhastrategy | = 4, then need to convert mb to pb ( done otherwise when calling info.weight(), [...] )
429  if( m_internal_event_number == 1 && std::abs(m_pythia->info.lhaStrategy()) == 4 ) {
431  ATH_MSG_DEBUG(" LHA strategy needs a conversion to fix Pythia8 shower weights bug(s) equal to " << m_conversion);
432  }
433 
434 
435  if(m_pythia->event.size() < 2){
436  ATH_MSG_ERROR("Something wrong with this event - it contains fewer than 2 particles!");
437  ATH_MSG_ERROR("internal event number is "<<m_internal_event_number);
438  return StatusCode::FAILURE;
439  }
440 
442 
443  if(m_lheFile != "" && m_storeLHE) addLHEToHepMC(evt);
444 
445  // in debug mode you can check whether the pdf information is stored
446  if(evt->pdf_info()){
447 #ifdef HEPMC3
448  ATH_MSG_DEBUG("PDFinfo id1:" << evt->pdf_info()->parton_id[0]);
449  ATH_MSG_DEBUG("PDFinfo id2:" << evt->pdf_info()->parton_id[1]);
450  ATH_MSG_DEBUG("PDFinfo x1:" << evt->pdf_info()->x[0]);
451  ATH_MSG_DEBUG("PDFinfo x2:" << evt->pdf_info()->x[1]);
452  ATH_MSG_DEBUG("PDFinfo scalePDF:" << evt->pdf_info()->scale);
453  ATH_MSG_DEBUG("PDFinfo pdf1:" << evt->pdf_info()->pdf_id[0]);
454  ATH_MSG_DEBUG("PDFinfo pdf2:" << evt->pdf_info()->pdf_id[1]);
455 #else
456  ATH_MSG_DEBUG("PDFinfo id1:" << evt->pdf_info()->id1());
457  ATH_MSG_DEBUG("PDFinfo id2:" << evt->pdf_info()->id2());
458  ATH_MSG_DEBUG("PDFinfo x1:" << evt->pdf_info()->x1());
459  ATH_MSG_DEBUG("PDFinfo x2:" << evt->pdf_info()->x2());
460  ATH_MSG_DEBUG("PDFinfo scalePDF:" << evt->pdf_info()->scalePDF());
461  ATH_MSG_DEBUG("PDFinfo pdf1:" << evt->pdf_info()->pdf1());
462  ATH_MSG_DEBUG("PDFinfo pdf2:" << evt->pdf_info()->pdf2());
463 #endif
464  }
465  else
466  ATH_MSG_DEBUG("No PDF information available in HepMC::GenEvent!");
467 
468  // set the randomseeds
470 
471  // fill weights
473 
474  return StatusCode::SUCCESS;
475 }
476 
479 
480  // reset
481  m_mergingWeight = m_pythia->info.mergingWeightNLO(); // first initialisation, good for the nominal weight in any case (see Merging:includeWeightInXsection).
482  m_enhanceWeight = 1.0; // better to keep the enhancement from UserHooks in a separate variable, to keep the code clear
483 
484 #ifndef PYTHIA8_304SERIES
485  // include Enhance userhook weight
486  for(const auto &hook: m_userHooksPtrs) {
487  if (hook->canEnhanceEmission()) {
488  m_enhanceWeight *= hook->getEnhancedEventWeight();
489  }
490  }
491 #endif // not PYTHIA8_304SERIES
492 
493  // DO NOT try to distinguish between phase space and merging contributions: only their product contains both, so always multiply them in order to be robust
494  double eventWeight = m_pythia->info.weight() * m_mergingWeight * m_enhanceWeight;
495 
496  std::map<std::string,double> fWeights; // temporary weight vector, needed while managing hepmc2 and 3 simultaneously
497 
498  // save as Default the usual pythia8 weight, including enhancements
499  // NB: info.weight() is built upon info.eventWeightLHEF (but includes shower "decorations"), not from the rwgt LHE vector.
500  size_t atlas_specific_weights = 1;
501  fWeights["Default"]=eventWeight;
502  if(m_internal_event_number == 1) {
503  ATH_MSG_INFO("found LHEF version "<< m_pythia->info.LHEFversion() );
504  if (m_pythia->info.LHEFversion() > 1) m_doLHE3Weights = true;
505  m_weightIDs.clear();
506  m_weightIDs.push_back("Default"); // notice that we are assigning a weightname = weightID
507  }
508 
509  // Now systematic weights: a) generator and b) shower variations
510  // merging implies reading from lhe files (while the opposite is not true, ok, but still works)
511  if (m_lheFile!="") {
512  // remember that the true merging component can be disentangled only when there are LHE input events
513 
514  // make sure to get the merging weight correctly: this is needed -only- for systematic weights (generator and parton shower variations)
515  // NB: most robust way, regardless of the specific value of Merging:includeWeightInXsection (if on, info.mergingWeight() is always 1.0 ! )
516  m_mergingWeight *= ( m_pythia->info.weight() / m_pythia->info.eventWeightLHEF ); // this is the actual merging component, regardless of conventions,
517  // needed by systematic variation weights
518  // this includes rare compensation or selection-biased weights
519  }
520 
521 
522  ATH_MSG_DEBUG("Event weights: enhancing weight, merging weight, total weight = "<<m_enhanceWeight<<", "<<m_mergingWeight<<", "<<eventWeight);
523 
524  // we already filled the "Default" weight
525  std::vector<std::string>::const_iterator id = m_weightIDs.begin()+atlas_specific_weights;
526 
527  // a) fill generator weights
528  if(m_pythia->info.getWeightsDetailedSize() != 0){
529  for(std::map<std::string, Pythia8::LHAwgt>::const_iterator wgt = m_pythia->info.rwgt->wgts.begin();
530  wgt != m_pythia->info.rwgt->wgts.end(); ++wgt){
531 
532  if(m_internal_event_number == 1){
533  m_weightIDs.push_back(wgt->first);
534  }else{
535  if(*id != wgt->first){
536  ATH_MSG_ERROR("Mismatch in LHE3 weight id. Found "<<wgt->first<<", expected "<<*id);
537  return StatusCode::FAILURE;
538  }
539  ++id;
540  }
541 
542  std::map<std::string, Pythia8::LHAweight>::const_iterator weightName = m_pythia->info.init_weights->find(wgt->first);
543  if(weightName != m_pythia->info.init_weights->end()){
544  fWeights[weightName->second.contents] = m_mergingWeight * m_enhanceWeight * wgt->second.contents;
545  }else{
546  // if no name was assigned/found, assign a weightname = weightid
547  fWeights[wgt->first] = m_mergingWeight * m_enhanceWeight * wgt->second.contents;
548  }
549 
550  }
551  }
552 
553  // b) shower weight variations
554  // always start from second shower weight: the first was saved already as "Default"
555 
556  for(int iw = 1; iw < m_pythia->info.PYTHIA8_NWEIGHTS(); ++iw){
557 
558  std::string wtName = ((int)m_showerWeightNames.size() == m_pythia->info.PYTHIA8_NWEIGHTS())? m_showerWeightNames[iw]: "ShowerWt_" +std::to_string(iw);
559 
560  fWeights[wtName] = m_mergingWeight * m_enhanceWeight * m_pythia->info.PYTHIA8_WEIGHT(iw)*m_conversion;
561 
562  if(m_internal_event_number == 1) {
563  m_weightIDs.push_back(wtName);
564  ATH_MSG_DEBUG("Shower weight name, value, conversion: "<<wtName<<", "<< fWeights[wtName] <<","<<m_conversion );
565  }
566  }
567 
568  // Now save, as a backup, also the LHEF weight without enhancements (useful for possible, rare, non-default cases)
569  // to make clear that it should not be used in analyses, save it always with a -10 factor (so that its goal is clear even if not checking its name)
570  if (m_lheFile!="")
571  {
572  fWeights["AUX_bare_not_for_analyses"]=(-10.0)*m_pythia->info.eventWeightLHEF;
573  if(m_internal_event_number == 1) m_weightIDs.push_back("AUX_bare_not_for_analyses");
574  }
575 
576  // Sad, but needed: create a string vector with acceptable order of weight names
577  if(m_internal_event_number == 1){
578  m_weightNames.clear();
579  for(const std::string &id : m_weightIDs){
580  if(m_doLHE3Weights) {
581  std::map<std::string, Pythia8::LHAweight>::const_iterator weight = m_pythia->info.init_weights->find(id);
582  if(weight != m_pythia->info.init_weights->end()) m_weightNames.push_back(weight->second.contents);
583  else m_weightNames.push_back(id);
584  }
585  else {
586  m_weightNames.push_back(id);
587  }
588  }
589  if (m_weightNames.size() != fWeights.size() ) {
590  ATH_MSG_ERROR("Something wrong when building list of weight names: " << m_weightNames.size() << " vs "<< fWeights.size() << ", exiting ...");
591  return StatusCode::FAILURE;
592  }
593  }
594 
595  // The following depends on the specific hepmc2/3 implementation
596 #ifdef HEPMC3
597  if (!evt->run_info()) {
598  evt->set_run_info(m_runinfo);
599  }
600  evt->run_info()->set_weight_names(m_weightNames);
601 
602  // for the first event, weight AUX_bare_not_for_analyses is not present in evt->weights(), so we need to book a place for it by hand
603  if (m_internal_event_number == 1 && evt->run_info()->weight_names().size() == evt->weights().size()+1 ) {
604  evt->weights().push_back(1.0);
605  }
606 
607  // added conversion GeV -> MeV to ensure correct units
608  evt->set_units(HepMC3::Units::MEV, HepMC3::Units::MM);
609 
610  evt->weights().resize(fWeights.size(), 1.0);
611  for (auto w: fWeights) {
612  evt->weight(w.first)=w.second;
613  }
614 
615  auto beams=evt->beams();
616  ATH_MSG_DEBUG( " Energy of the beams " << beams[0]->momentum().e() );
617 
618 //uncomment to list HepMC events
619 // std::cout << " print::listing Pythia8 " << std::endl;
620 // HepMC3::Print::listing(std::cout, *evt);
621 
622 #else
623  evt->weights().clear();
624  for (auto w: m_weightNames ) {evt->weights()[w]=fWeights[w];}
625  auto beams=evt->beam_particles();
626  ATH_MSG_DEBUG( " Energy of the beams " << beams.first->momentum().e() );
627 
628 //uncomment to list HepMC events
629 // std::cout << " print::listing Pythia8 " << std::endl;
630 // evt->print();
631 #endif
632 
633  return StatusCode::SUCCESS;
634 }
635 
638 
639  ATH_MSG_INFO(">>> Pythia8_i from genFinalize");
640  m_pythia->stat();
641 
642  Pythia8::Info info = m_pythia->info;
643  double xs = info.sigmaGen(); // in mb
644 
646  const double accfactor = m_nMerged / info.nAccepted();
647  ATH_MSG_DEBUG("Multiplying cross-section by CKKWL merging acceptance of "<<m_nMerged <<"/" <<info.nAccepted() << " = " << accfactor
648  << ": " << xs << " -> " << xs*accfactor);
649  xs *= accfactor;
650  }
651 
652  if(m_doFxFxXS){
653  ATH_MSG_DEBUG("Using FxFx cross section recipe: xs = "<< m_sigmaTotal << " / " << 1e9*info.nTried());
654  xs = m_sigmaTotal / (1e9*info.nTried());
655  std::cout << "Using FxFx cross section recipe: xs = "<< m_sigmaTotal << " / " << 1e9*info.nTried() << std::endl;
656  }
657 
658  if( ! m_athenaTool.empty()){
659  double xsmod = m_athenaTool->CrossSectionScaleFactor();
660  ATH_MSG_DEBUG("Multiplying cross-section by Pythia Modifier tool factor " << xsmod );
661  xs *= xsmod;
662  }
663 
664  xs *= 1000. * 1000.;//convert to nb
665 
666  std::cout << "MetaData: cross-section (nb)= " << xs <<std::endl;
667  std::cout << "MetaData: generator= Pythia 8." << std::string(py8version()) <<std::endl;
668 
669  if(m_doLHE3Weights || m_weightIDs.size()>1 ){
670  std::cout<<"MetaData: weights = ";
671  for (auto w : m_weightNames ) std::cout<< w <<" | ";
672  std::cout<<std::endl;
673  }
674 
675  if (m_computeEfficiency){
676  if (info.nTried()>0) ATH_MSG_INFO("Pythia8 efficiency (nAccepted/nTried %) = " << info.nAccepted()*100./info.nTried());
677  else ATH_MSG_INFO("Pythia8 efficiency cannot be computed, nTried <=0");
678  }
679 
680 
681  return StatusCode::SUCCESS;
682 }
683 
685 void Pythia8_i::addLHEToHepMC(HepMC::GenEvent *evt){
686 
687 #ifdef HEPMC3
688  HepMC::GenEvent *procEvent = new HepMC::GenEvent();
689 
690  // Adding the LHE event to the HepMC results in undecayed partons in the event record.
691  // Pythia's HepMC converter throws up undecayed partons, so we ignore that
692  // (expected) exception this time
693  m_pythiaToHepMC.fill_next_event(m_pythia->process, procEvent, evt->event_number(), &m_pythia->info, &m_pythia->settings);
694 
695  for(auto p: *procEvent){
696  p->set_status(HepMC::PYTHIA8LHESTATUS);
697  }
698 
699  //This code and the HepMC2 version below assume a correct input, e.g. beams[0]->end_vertex() exists.
700  for(auto& v: procEvent->vertices()) v->set_status(1);
701  auto beams=evt->beams();
702  auto procBeams=procEvent->beams();
703  if(beams[0]->momentum().pz() * procBeams[0]->momentum().pz() < 0.) std::swap(procBeams[0],procBeams[1]);
704  for (auto p: procBeams[0]->end_vertex()->particles_out()) beams[0]->end_vertex()->add_particle_out(p);
705  for (auto p: procBeams[1]->end_vertex()->particles_out()) beams[1]->end_vertex()->add_particle_out(p);
706 
707  HepMC::fillBarcodesAttribute(procEvent);
708 #else
709  HepMC::GenEvent *procEvent = new HepMC::GenEvent(evt->momentum_unit(), evt->length_unit());
710 
711  // Adding the LHE event to the HepMC results in undecayed partons in the event record.
712  // Pythia's HepMC converter throws up undecayed partons, so we ignore that
713  // (expected) exception this time
714  try{
715  m_pythiaToHepMC.fill_next_event(m_pythia->process, procEvent, evt->event_number(), &m_pythia->info, &m_pythia->settings);
716  }catch(HepMC::PartonEndVertexException &ignoreIt){}
717 
718  for(HepMC::GenEvent::particle_iterator p = procEvent->particles_begin();
719  p != procEvent->particles_end(); ++p){
720  (*p)->set_status(HepMC::PYTHIA8LHESTATUS);
721  }
722 
723  std::vector<HepMC::GenParticle*> beams;
724  std::vector<HepMC::GenParticle*> procBeams;
725  beams.push_back(evt->beam_particles().first);
726  beams.push_back(evt->beam_particles().second);
727 
728  if(beams[0]->momentum().pz() * procEvent->beam_particles().first->momentum().pz() > 0.){
729  procBeams.push_back(procEvent->beam_particles().first);
730  procBeams.push_back(procEvent->beam_particles().second);
731  }else{
732  procBeams.push_back(procEvent->beam_particles().second);
733  procBeams.push_back(procEvent->beam_particles().first);
734  }
735 
736  std::map<const HepMC::GenVertex*, HepMC::GenVertex*> vtxCopies;
737 
738  for(HepMC::GenEvent::vertex_const_iterator v = procEvent->vertices_begin();
739  v != procEvent->vertices_end(); ++v ) {
740  if(*v == procBeams[0]->end_vertex() || *v == procBeams[1]->end_vertex()) continue;
741  HepMC::GenVertex* vCopy = new HepMC::GenVertex((*v)->position(), (*v)->id(), (*v)->weights());
742  vCopy->suggest_barcode(-(evt->vertices_size()));
743  vCopy->set_id(1);
744  vtxCopies[*v] = vCopy;
745  evt->add_vertex(vCopy);
746  }
747 
748  for(HepMC::GenEvent::particle_const_iterator p = procEvent->particles_begin();
749  p != procEvent->particles_end(); ++p ){
750  if((*p)->is_beam()) continue;
751 
752  HepMC::GenParticle *pCopy = new HepMC::GenParticle(*(*p));
753  pCopy->suggest_barcode(evt->particles_size());
754 
756  for(size_t ii =0; ii != 2; ++ii){
757  if((*p)->production_vertex() == procBeams[ii]->end_vertex()){
758  beams[ii]->end_vertex()->add_particle_out(pCopy);
759  break;
760  }
761 
762  if(ii == 1){
763  vit = vtxCopies.find((*p)->production_vertex());
764  if(vit != vtxCopies.end()) vit->second->add_particle_out(pCopy);
765  }
766  }
767 
768  vit = vtxCopies.find((*p)->end_vertex());
769  if(vit != vtxCopies.end()) vit->second->add_particle_in(pCopy);
770  }
771 #endif
772 
773  return;
774 }
775 
778  return m_version;
779 }
780 
782 const std::string& Pythia8_i::pythia_stream() {
783  return s_pythia_stream;
784 }
785 
787 std::string Pythia8_i::xmlpath(){
788 
789 
790  std::string foundpath = "";
791 
792 // Try to find the xmldoc directory using PathResolver:
793  foundpath = PathResolverFindCalibDirectory( "Pythia8/xmldoc" );
794 
795  return foundpath;
796 }
797 
799 
800 // fix Pythia8 shower weights change in conventions
801 #ifdef PYTHIA8_NWEIGHTS
802  #undef PYTHIA8_NWEIGHTS
803  #undef PYTHIA8_WEIGHT
804  #undef PYTHIA8_WLABEL
805  #undef PYTHIA8_CONVERSION
806 #endif
grepfile.info
info
Definition: grepfile.py:38
Pythia8_i::NEUTRON
@ NEUTRON
Definition: Pythia8_i.h:115
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
read
IovVectorMap_t read(const Folder &theFolder, const SelectionCriterion &choice, const unsigned int limit=10)
Definition: openCoraCool.cxx:569
Pythia8_i::m_maxFailures
UnsignedIntegerProperty m_maxFailures
Definition: Pythia8_i.h:90
Pythia8_i::m_enhanceWeight
double m_enhanceWeight
Definition: Pythia8_i.h:158
Pythia8_i::m_nMerged
double m_nMerged
Definition: Pythia8_i.h:131
ForwardTracker::beam1
@ beam1
Definition: ForwardTrackerConstants.h:13
Pythia8_i::fillWeights
virtual StatusCode fillWeights(HepMC::GenEvent *evt)
Definition: Pythia8_i.cxx:478
Pythia8_i::MUON
@ MUON
Definition: Pythia8_i.h:115
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
Pythia8_i::m_version
double m_version
Definition: Pythia8_i.h:109
Pythia8_i::m_procPtr
std::shared_ptr< Pythia8::Sigma2Process > m_procPtr
Definition: Pythia8_i.h:144
ForwardTracker::beam2
@ beam2
Definition: ForwardTrackerConstants.h:13
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
Pythia8_i::xmlpath
static std::string xmlpath()
Definition: Pythia8_i.cxx:787
Pythia8_i::m_particleDataFile
StringProperty m_particleDataFile
Definition: Pythia8_i.h:154
Pythia8_i::m_weightNames
std::vector< std::string > m_weightNames
Definition: Pythia8_i.h:160
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
rerun_display.cmd
string cmd
Definition: rerun_display.py:67
Pythia8_i::m_failureCount
unsigned int m_failureCount
Definition: Pythia8_i.h:135
Pythia8_i::ELECTRON
@ ELECTRON
Definition: Pythia8_i.h:115
Pythia8_i::m_athenaTool
PublicToolHandle< IPythia8Custom > m_athenaTool
Definition: Pythia8_i.h:166
HepMC::PYTHIA8LHESTATUS
constexpr int PYTHIA8LHESTATUS
Definition: MagicNumbers.h:43
MM
@ MM
Definition: RegSelEnums.h:38
Pythia8_i::pythiaVersion
double pythiaVersion() const
Definition: Pythia8_i.cxx:777
Pythia8_i::m_userHooks
StringArrayProperty m_userHooks
Definition: Pythia8_i.h:96
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
Pythia8_i::m_pt0timesMPI
DoubleProperty m_pt0timesMPI
Definition: Pythia8_i.h:98
HepMC::fillBarcodesAttribute
void fillBarcodesAttribute(GenEvent *)
Definition: GenEvent.h:504
Pythia8_i.h
Pythia8_i::m_showerWeightNamesProp
StringArrayProperty m_showerWeightNamesProp
Definition: Pythia8_i.h:164
Pythia8_i::ANTIPROTON
@ ANTIPROTON
Definition: Pythia8_i.h:115
Pythia8_i::ANTINEUTRON
@ ANTINEUTRON
Definition: Pythia8_i.h:115
Pythia8_i::m_userHooksPtrs
std::vector< UserHooksPtrType > m_userHooksPtrs
Definition: Pythia8_i.h:146
PathResolverFindCalibDirectory
std::string PathResolverFindCalibDirectory(const std::string &logical_file_name)
Definition: PathResolver.cxx:432
Pythia8_i::m_doFxFxXS
BooleanProperty m_doFxFxXS
Definition: Pythia8_i.h:128
dqt_zlumi_pandas.weight
int weight
Definition: dqt_zlumi_pandas.py:200
Pythia8_UserResonance::UserResonanceFactory::create
static std::shared_ptr< ResonanceWidths > create(const std::string &name, int pdgid)
Call this with the name of the ResonanceWidth and PDG ID to which it will be applied e....
Definition: UserResonanceFactory.cxx:13
Pythia8_i::m_doLHE3Weights
bool m_doLHE3Weights
Definition: Pythia8_i.h:161
GenModule
Base class for common behaviour of generator interfaces.
Definition: GenModule.h:39
Pythia8_i::m_userResonancePtrs
std::vector< std::shared_ptr< Pythia8::ResonanceWidths > > m_userResonancePtrs
Definition: Pythia8_i.h:150
Pythia8_i::fillEvt
virtual StatusCode fillEvt(HepMC::GenEvent *evt)
For filling the HepMC event object.
Definition: Pythia8_i.cxx:422
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ParticleGun_EoverP_Config.momentum
momentum
Definition: ParticleGun_EoverP_Config.py:63
Pythia8_i::m_numberAlphaS
DoubleProperty m_numberAlphaS
Definition: Pythia8_i.h:99
McEventCollection.h
Pythia8_i::m_showerWeightNames
std::vector< std::string > m_showerWeightNames
Definition: Pythia8_i.h:163
Pythia8_UserProcess::UserProcessFactory::create
static std::shared_ptr< Sigma2Process > create(const std::string &procName)
Definition: UserProcessFactory.cxx:11
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
Pythia8_i::m_atlasRndmEngine
std::shared_ptr< customRndm > m_atlasRndmEngine
Definition: Pythia8_i.h:93
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
PYTHIA8_CONVERSION
#define PYTHIA8_CONVERSION
Definition: Pythia8_i.cxx:32
Pythia8_i::callGenerator
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
Definition: Pythia8_i.cxx:356
UserResonanceFactory.h
UserProcessFactory.h
Amg::pz
@ pz
Definition: GeoPrimitives.h:40
Pythia8_i::genFinalize
virtual StatusCode genFinalize()
For finalising the generator, if required.
Definition: Pythia8_i.cxx:637
Pythia8_i::m_nAccepted
double m_nAccepted
Definition: Pythia8_i.h:130
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
ppToJpsimu0mu0.SuppressSmallPT
SuppressSmallPT
Definition: ppToJpsimu0mu0.py:26
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
beamspotman.stat
stat
Definition: beamspotman.py:266
Pythia8_i::m_beam2
StringProperty m_beam2
Definition: Pythia8_i.h:121
Pythia8_i::m_lheFile
StringProperty m_lheFile
Definition: Pythia8_i.h:124
Pythia8_i::m_sigmaTotal
double m_sigmaTotal
Definition: Pythia8_i.h:132
Pythia8_i::m_SuppressSmallPT
Pythia8::SuppressSmallPT * m_SuppressSmallPT
Definition: Pythia8_i.h:170
min
#define min(a, b)
Definition: cfImp.cxx:40
PathResolver.h
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:194
Pythia8_i::m_weightIDs
std::vector< std::string > m_weightIDs
Definition: Pythia8_i.h:159
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
MagicNumbers.h
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
Pythia8_i::~Pythia8_i
~Pythia8_i()
Definition: Pythia8_i.cxx:84
Pythia8_i::LEAD
@ LEAD
Definition: Pythia8_i.h:115
PYTHIA8_PTRWRAP
#define PYTHIA8_PTRWRAP(A)
Definition: UserHooksFactory.h:14
RNGWrapper.h
Pythia8_i::PDGID
PDGID
Definition: Pythia8_i.h:115
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
Pythia8_i::Pythia8_i
Pythia8_i(const std::string &name, ISvcLocator *pSvcLocator)
Definition: Pythia8_i.cxx:68
Pythia8_i::m_userProcess
StringProperty m_userProcess
Definition: Pythia8_i.h:141
Pythia8_i::m_seeds
std::vector< long int > m_seeds
Definition: Pythia8_i.h:139
python.PyAthena.v
v
Definition: PyAthena.py:157
Pythia8_i::m_particleIDs
std::map< std::string, PDGID > m_particleIDs
Definition: Pythia8_i.h:137
Pythia8_i::POSITRON
@ POSITRON
Definition: Pythia8_i.h:115
Pythia8_i::m_mergingWeight
double m_mergingWeight
Definition: Pythia8_i.h:157
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
Pythia8_i::ANTIMUON
@ ANTIMUON
Definition: Pythia8_i.h:115
Pythia8_i::addLHEToHepMC
void addLHEToHepMC(HepMC::GenEvent *evt)
Definition: Pythia8_i.cxx:685
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
Pythia8_i::m_outputParticleDataFile
StringProperty m_outputParticleDataFile
Definition: Pythia8_i.h:155
Pythia8_i::m_conversion
double m_conversion
Definition: Pythia8_i.h:133
Pythia8_i::m_dsid
IntegerProperty m_dsid
Definition: Pythia8_i.h:95
Pythia8_i::m_override_transform_beamenergy
bool m_override_transform_beamenergy
Definition: Pythia8_i.h:122
ATHRNG::calculateSeedsMC21
void calculateSeedsMC21(long *seeds, const std::string &algName, uint64_t ev, uint64_t run, uint64_t offset=0)
Set the random seed using a string (e.g.
Definition: RNGWrapper.cxx:37
Pythia8_i::m_sameAlphaSAsMPI
BooleanProperty m_sameAlphaSAsMPI
Definition: Pythia8_i.h:100
Pythia8_i::m_userResonances
StringProperty m_userResonances
Definition: Pythia8_i.h:148
Pythia8_i::m_doCKKWLAcceptance
BooleanProperty m_doCKKWLAcceptance
Definition: Pythia8_i.h:127
Pythia8_i::m_commands
StringArrayProperty m_commands
Definition: Pythia8_i.h:111
merge.status
status
Definition: merge.py:17
Pythia8_i::m_storeLHE
BooleanProperty m_storeLHE
Definition: Pythia8_i.h:126
CI_EMPFlowData22test.returnCode
returnCode
Definition: CI_EMPFlowData22test.py:16
Pythia8_i::m_collisionEnergy
DoubleProperty m_collisionEnergy
Definition: Pythia8_i.h:117
Pythia8_i::m_useRndmGenSvc
BooleanProperty m_useRndmGenSvc
Definition: Pythia8_i.h:92
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:200
Pythia8_i::PROTON
@ PROTON
Definition: Pythia8_i.h:115
Pythia8_i::m_beam1
StringProperty m_beam1
Definition: Pythia8_i.h:120
Pythia8_UserHooks::UserHooksFactory::create
static UserHooks * create(const std::string &hookName)
Definition: UserHooksFactory.cxx:10
Pythia8_i::genInitialize
virtual StatusCode genInitialize()
For initializing the generator, if required.
Definition: Pythia8_i.cxx:96
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
Pythia8_i::m_internal_event_number
int m_internal_event_number
Definition: Pythia8_i.h:107
Pythia8_i::pythia_stream
static const std::string & pythia_stream()
Definition: Pythia8_i.cxx:782
Pythia8_i::m_pythia
std::unique_ptr< Pythia8::Pythia > m_pythia
Definition: Pythia8_i.h:88
Pythia8_i::m_computeEfficiency
BooleanProperty m_computeEfficiency
Definition: Pythia8_i.h:129
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
Pythia8_i::m_pythiaToHepMC
HepMC::Pythia8ToHepMC m_pythiaToHepMC
Definition: Pythia8_i.h:89
GenParticle
@ GenParticle
Definition: TruthClasses.h:30
HepMC::set_random_states
void set_random_states(GenEvent *e, std::vector< T > a)
Definition: GenEvent.h:525