StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
HepMC2.h
1 // HepMC2.h is a part of the PYTHIA event generator.
2 // Copyright (C) 2020 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // Author: Mikhail Kirsanov, Mikhail.Kirsanov@cern.ch
7 // Exception classes provided by James Monk, with minor changes.
8 // Header file and function definitions for the Pythia8ToHepMC class,
9 // which converts a PYTHIA event record to the standard HepMC format.
10 
11 #ifndef Pythia8_HepMC2_H
12 #define Pythia8_HepMC2_H
13 
14 #include <exception>
15 #include <sstream>
16 #include <vector>
17 #include "HepMC/IO_BaseClass.h"
18 #include "HepMC/IO_GenEvent.h"
19 #include "HepMC/GenEvent.h"
20 #include "HepMC/Units.h"
21 #include "Pythia8/Pythia.h"
22 
23 namespace HepMC {
24 
25 //==========================================================================
26 
27 // Base exception for all exceptions that Pythia8ToHepMC might throw.
28 
29 class Pythia8ToHepMCException : public std::exception {
30 
31 public:
32  virtual const char* what() const throw() { return "Pythia8ToHepMCException";}
33 
34 };
35 
36 //--------------------------------------------------------------------------
37 
38 // Exception thrown when an undecayed parton is written into the record.
39 
40 class PartonEndVertexException : public Pythia8ToHepMCException {
41 
42 public:
43 
44  // Constructor and destructor.
45  PartonEndVertexException(int i, int pdg_idIn) : Pythia8ToHepMCException() {
46  iSave = i;
47  idSave = pdg_idIn;
48  std::stringstream ss;
49  ss << "Bad end vertex at " << i << " for flavour " << pdg_idIn;
50  msg = ss.str();
51  }
52  virtual ~PartonEndVertexException() throw() {}
53 
54  // Throw exception.
55  virtual const char* what() const throw() {return msg.c_str();}
56 
57  // Return info on location and flavour of bad parton.
58  int index() const {return iSave;}
59  int pdg_id() const {return idSave;}
60 
61 protected:
62 
63  std::string msg;
64  int iSave, idSave;
65 };
66 
67 //==========================================================================
68 
69 // The Pythia8ToHepMC class.
70 
71 class Pythia8ToHepMC : public IO_BaseClass {
72 
73 public:
74 
75  // Constructor and destructor.
76  Pythia8ToHepMC() : m_internal_event_number(0), m_print_inconsistency(true),
77  m_free_parton_exception(true), m_convert_gluon_to_0(false),
78  m_store_pdf(true), m_store_proc(true), m_store_xsec(true) {;}
79  virtual ~Pythia8ToHepMC() {;}
80 
81  // The recommended method to convert Pythia events into HepMC ones.
82  bool fill_next_event( Pythia8::Pythia& pythia, GenEvent* evt,
83  int ievnum = -1, bool append = false, GenParticle* rootParticle = 0,
84  int iBarcode = -1 ) {return fill_next_event( pythia.event, evt, ievnum,
85  &pythia.info, &pythia.settings, append, rootParticle, iBarcode);}
86 
87  // Alternative method to convert Pythia events into HepMC ones.
88  bool fill_next_event( Pythia8::Event& pyev, GenEvent* evt,
89  int ievnum = -1, const Pythia8::Info* pyinfo = 0,
90  Pythia8::Settings* pyset = 0, bool append = false,
91  GenParticle* rootParticle = 0, int iBarcode = -1);
92 
93  // Read out values for some switches.
94  bool print_inconsistency() const {return m_print_inconsistency;}
95  bool free_parton_exception() const {return m_free_parton_exception;}
96  bool convert_gluon_to_0() const {return m_convert_gluon_to_0;}
97  bool store_pdf() const {return m_store_pdf;}
98  bool store_proc() const {return m_store_proc;}
99  bool store_xsec() const {return m_store_xsec;}
100 
101  // Set values for some switches.
102  void set_print_inconsistency(bool b = true) {m_print_inconsistency = b;}
103  void set_free_parton_exception(bool b = true) {m_free_parton_exception = b;}
104  void set_convert_gluon_to_0(bool b = false) {m_convert_gluon_to_0 = b;}
105  void set_store_pdf(bool b = true) {m_store_pdf = b;}
106  void set_store_proc(bool b = true) {m_store_proc = b;}
107  void set_store_xsec(bool b = true) {m_store_xsec = b;}
108 
109 private:
110 
111  // Following methods are not implemented for this class.
112  virtual bool fill_next_event( GenEvent* ) { return 0; }
113  virtual void write_event( const GenEvent* ) {;}
114 
115  // Use of copy constructor is not allowed.
116  Pythia8ToHepMC( const Pythia8ToHepMC& ) : IO_BaseClass() {;}
117 
118  // Data members.
119  int m_internal_event_number;
120  bool m_print_inconsistency, m_free_parton_exception, m_convert_gluon_to_0,
121  m_store_pdf, m_store_proc, m_store_xsec;
122 
123 };
124 
125 //==========================================================================
126 
127 // Main method for conversion from PYTHIA event to HepMC event.
128 // Read one event from Pythia8 and fill a new GenEvent, alternatively
129 // append to an existing GenEvent, and return T/F = success/failure.
130 
131 inline bool Pythia8ToHepMC::fill_next_event( Pythia8::Event& pyev,
132  GenEvent* evt, int ievnum, const Pythia8::Info* pyinfo,
133  Pythia8::Settings* pyset, bool append, GenParticle* rootParticle,
134  int iBarcode) {
135 
136  // 1. Error if no event passed.
137  if (!evt) {
138  std::cout << " Pythia8ToHepMC::fill_next_event error: passed null event."
139  << std::endl;
140  return 0;
141  }
142 
143  // Update event number counter.
144  if (!append) {
145  if (ievnum >= 0) {
146  evt->set_event_number(ievnum);
147  m_internal_event_number = ievnum;
148  } else {
149  evt->set_event_number(m_internal_event_number);
150  ++m_internal_event_number;
151  }
152  }
153 
154  // Conversion factors from Pythia units GeV and mm to HepMC ones.
155  double momFac = HepMC::Units::conversion_factor(HepMC::Units::GEV,
156  evt->momentum_unit());
157  double lenFac = HepMC::Units::conversion_factor(HepMC::Units::MM,
158  evt->length_unit());
159 
160  // Set up for alternative to append to an existing event.
161  int iStart = 1;
162  int newBarcode = 0;
163  if (append) {
164  if (!rootParticle) {
165  std::cout << " Pythia8ToHepMC::fill_next_event error: passed null "
166  << "root particle in append mode." << std::endl;
167  return 0;
168  }
169  iStart = 2;
170  newBarcode = (iBarcode > -1) ? iBarcode : evt->particles_size();
171  // New vertex associated with appended particles.
172  GenVertex* prod_vtx0 = new GenVertex();
173  prod_vtx0->add_particle_in( rootParticle );
174  evt->add_vertex( prod_vtx0 );
175  }
176 
177  // 2. Create a particle instance for each entry and fill a map, and
178  // a vector which maps from the particle index to the GenParticle address.
179  std::vector<GenParticle*> hepevt_particles( pyev.size() );
180  for (int i = iStart; i < pyev.size(); ++i) {
181 
182  // Fill the particle.
183  hepevt_particles[i] = new GenParticle(
184  FourVector( momFac * pyev[i].px(), momFac * pyev[i].py(),
185  momFac * pyev[i].pz(), momFac * pyev[i].e() ),
186  pyev[i].id(), pyev[i].statusHepMC() );
187  if (iBarcode != 0) ++newBarcode;
188  hepevt_particles[i]->suggest_barcode( (append) ? newBarcode : i );
189  hepevt_particles[i]->set_generated_mass( momFac * pyev[i].m() );
190 
191  // Colour flow uses index 1 and 2.
192  int colType = pyev[i].colType();
193  if (colType == 1 || colType == 2)
194  hepevt_particles[i]->set_flow(1, pyev[i].col());
195  if (colType == -1 || colType == 2)
196  hepevt_particles[i]->set_flow(2, pyev[i].acol());
197  }
198 
199  // Here we assume that the first two particles in the list
200  // are the incoming beam particles.
201  if (!append)
202  evt->set_beam_particles( hepevt_particles[1], hepevt_particles[2] );
203 
204  // 3. Loop over particles AGAIN, this time creating vertices.
205  // We build the production vertex for each entry in hepevt.
206  // The HEPEVT pointers are bi-directional, so gives decay vertices as well.
207  for (int i = iStart; i < pyev.size(); ++i) {
208  GenParticle* p = hepevt_particles[i];
209 
210  // 3a. Search to see if a production vertex already exists.
211  std::vector<int> mothers = pyev[i].motherList();
212  unsigned int imother = 0;
213  int mother = -1; // note that in Pythia8 there is a particle number 0!
214  if ( !mothers.empty() ) mother = mothers[imother];
215  GenVertex* prod_vtx = p->production_vertex();
216  while ( !prod_vtx && mother > 0 ) {
217  prod_vtx = (append && mother == 1) ? rootParticle->end_vertex()
218  : hepevt_particles[mother]->end_vertex();
219  if (prod_vtx) prod_vtx->add_particle_out( p );
220  mother = ( ++imother < mothers.size() ) ? mothers[imother] : -1;
221  }
222 
223  // 3b. If no suitable production vertex exists - and the particle has
224  // at least one mother or position information to store - make one.
225  FourVector prod_pos( lenFac * pyev[i].xProd(), lenFac * pyev[i].yProd(),
226  lenFac * pyev[i].zProd(), lenFac * pyev[i].tProd() );
227  if ( !prod_vtx && ( mothers.size() > 0 || prod_pos != FourVector() ) ) {
228  prod_vtx = new GenVertex();
229  prod_vtx->add_particle_out( p );
230  evt->add_vertex( prod_vtx );
231  }
232 
233  // 3c. If prod_vtx doesn't already have position specified, fill it.
234  if ( prod_vtx && prod_vtx->position() == FourVector() )
235  prod_vtx->set_position( prod_pos );
236 
237  // 3d. loop over mothers to make sure their end_vertices are consistent.
238  imother = 0;
239  mother = -1;
240  if ( !mothers.empty() ) mother = mothers[imother];
241  while ( prod_vtx && mother > 0 ) {
242 
243  // If end vertex of the mother isn't specified, do it now.
244  GenParticle* ppp = (append && mother == 1) ? rootParticle
245  : hepevt_particles[mother];
246  if ( !ppp->end_vertex() ) {
247  prod_vtx->add_particle_in( ppp );
248 
249  // Problem scenario: the mother already has a decay vertex which
250  // differs from the daughter's production vertex. This means there is
251  // internal inconsistency in the HEPEVT event record. Print an error.
252  // Note: we could provide a fix by joining the two vertices with a
253  // dummy particle if the problem arises often.
254  } else if (ppp->end_vertex() != prod_vtx ) {
255  if ( m_print_inconsistency ) std::cout
256  << " Pythia8ToHepMC::fill_next_event: inconsistent mother/daugher "
257  << "information in Pythia8 event " << std::endl
258  << "i = " << i << " mother = " << mother
259  << "\n This warning can be turned off with the "
260  << "Pythia8ToHepMC::print_inconsistency switch." << std::endl;
261  }
262 
263  // End of vertex-setting loops.
264  mother = ( ++imother < mothers.size() ) ? mothers[imother] : -1;
265  }
266  }
267 
268  // If hadronization switched on then no final coloured particles.
269  bool doHadr = (pyset == 0) ? m_free_parton_exception
270  : pyset->flag("HadronLevel:all") && pyset->flag("HadronLevel:Hadronize");
271 
272  // 4. Check for particles which come from nowhere, i.e. are without
273  // mothers or daughters. These need to be attached to a vertex, or else
274  // they will never become part of the event.
275  for (int i = iStart; i < pyev.size(); ++i) {
276  if ( !hepevt_particles[i]->end_vertex() &&
277  !hepevt_particles[i]->production_vertex() ) {
278  std::cout << " Pythia8ToHepMC::fill_next_event error: "
279  << "hanging particle " << i << std::endl;
280  GenVertex* prod_vtx = new GenVertex();
281  prod_vtx->add_particle_out( hepevt_particles[i] );
282  evt->add_vertex( prod_vtx );
283  }
284 
285  // Also check for free partons (= gluons and quarks; not diquarks?).
286  if ( doHadr && m_free_parton_exception ) {
287  int pdg_tmp = hepevt_particles[i]->pdg_id();
288  if ( (abs(pdg_tmp) <= 6 || pdg_tmp == 21)
289  && !hepevt_particles[i]->end_vertex() )
290  throw PartonEndVertexException(i, pdg_tmp);
291  }
292  }
293 
294  // Done if only appending to already existing event.
295  if (append) return true;
296 
297  // 5. Store PDF, weight, cross section and other event information.
298  // Flavours of incoming partons.
299  if (m_store_pdf && pyinfo != 0) {
300  int id1pdf = pyinfo->id1pdf();
301  int id2pdf = pyinfo->id2pdf();
302  if ( m_convert_gluon_to_0 ) {
303  if (id1pdf == 21) id1pdf = 0;
304  if (id2pdf == 21) id2pdf = 0;
305  }
306 
307  // Store PDF information.
308  evt->set_pdf_info( PdfInfo( id1pdf, id2pdf, pyinfo->x1pdf(),
309  pyinfo->x2pdf(), pyinfo->QFac(), pyinfo->pdf1(), pyinfo->pdf2() ) );
310  }
311 
312  // Store process code, scale, alpha_em, alpha_s.
313  if (m_store_proc && pyinfo != 0) {
314  evt->set_signal_process_id( pyinfo->code() );
315  evt->set_event_scale( pyinfo->QRen() );
316  if (evt->alphaQED() <= 0) evt->set_alphaQED( pyinfo->alphaEM() );
317  if (evt->alphaQCD() <= 0) evt->set_alphaQCD( pyinfo->alphaS() );
318  }
319 
320  // Store cross-section information in pb and event weight. The latter is
321  // usually dimensionless, but in units of pb for Les Houches strategies +-4.
322  if (m_store_xsec && pyinfo != 0) {
324  xsec.set_cross_section( pyinfo->sigmaGen() * 1e9,
325  pyinfo->sigmaErr() * 1e9);
326  evt->set_cross_section(xsec);
327  for (int iweight = 0; iweight < pyinfo->numberOfWeights();
328  ++iweight) {
329  std::string name = pyinfo->weightNameByIndex(iweight);
330  double value = pyinfo->weightValueByIndex(iweight);
331  evt->weights()[name] = value;
332  }
333  // If multiweights with possibly different xsec, overwrite central value
334  std::vector<double> xsecVec = pyinfo->weightContainerPtr->getTotalXsec();
335  if (xsecVec.size() > 0) {
336  xsec.set_cross_section(xsecVec[0]*1e9);
337  evt->set_cross_section(xsec);
338  }
339  }
340 
341  // Done for new event.
342  return true;
343 
344 }
345 
346 //==========================================================================
347 
348 } // end namespace HepMC
349 
350 #endif // end Pythia8_HepMC2_H
void set_cross_section(double xs, double xs_err)
Set cross section and error in pb.
The GenCrossSection class stores the generated cross section.