File indexing completed on 2025-09-17 09:08:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef Pythia8_HepMC2_H
0014 #define Pythia8_HepMC2_H
0015
0016 #ifdef Pythia8_HepMC3_H
0017 #error Cannot include HepMC2.h if HepMC3.h has already been included.
0018 #endif
0019
0020 #include <exception>
0021 #include <sstream>
0022 #include <vector>
0023 #include "HepMC/IO_BaseClass.h"
0024 #include "HepMC/IO_GenEvent.h"
0025 #include "HepMC/GenEvent.h"
0026 #include "HepMC/Units.h"
0027 #include "Pythia8/Pythia.h"
0028 #include "Pythia8/HIInfo.h"
0029
0030 namespace HepMC {
0031
0032
0033
0034
0035
0036 class Pythia8ToHepMCException : public std::exception {
0037
0038 public:
0039 virtual const char* what() const throw() { return "Pythia8ToHepMCException";}
0040
0041 };
0042
0043
0044
0045
0046
0047 class PartonEndVertexException : public Pythia8ToHepMCException {
0048
0049 public:
0050
0051
0052 PartonEndVertexException(int i, int pdg_idIn) : Pythia8ToHepMCException() {
0053 iSave = i;
0054 idSave = pdg_idIn;
0055 std::stringstream ss;
0056 ss << "Bad end vertex at " << i << " for flavour " << pdg_idIn;
0057 msg = ss.str();
0058 }
0059 virtual ~PartonEndVertexException() throw() {}
0060
0061
0062 virtual const char* what() const throw() {return msg.c_str();}
0063
0064
0065 int index() const {return iSave;}
0066 int pdg_id() const {return idSave;}
0067
0068 protected:
0069
0070 std::string msg;
0071 int iSave, idSave;
0072 };
0073
0074
0075
0076
0077
0078 class Pythia8ToHepMC : public IO_BaseClass {
0079
0080 public:
0081
0082
0083 Pythia8ToHepMC() : m_internal_event_number(0), m_print_inconsistency(true),
0084 m_free_parton_exception(true), m_convert_gluon_to_0(false),
0085 m_store_pdf(true), m_store_proc(true), m_store_xsec(true),
0086 m_store_weights(true) {;}
0087 virtual ~Pythia8ToHepMC() {;}
0088
0089
0090 bool fill_next_event( Pythia8::Pythia& pythia, GenEvent& evt,
0091 int ievnum = -1, bool append = false, GenParticle* rootParticle = 0,
0092 int iBarcode = -1 ) {return fill_next_event( pythia.event, &evt, ievnum,
0093 &pythia.info, &pythia.settings, append, rootParticle, iBarcode);}
0094 bool fill_next_event( Pythia8::Pythia& pythia, GenEvent* evt,
0095 int ievnum = -1, bool append = false, GenParticle* rootParticle = 0,
0096 int iBarcode = -1 ) {return fill_next_event( pythia.event, evt, ievnum,
0097 &pythia.info, &pythia.settings, append, rootParticle, iBarcode);}
0098
0099
0100 bool fill_next_event( Pythia8::Event& pyev, GenEvent& evt,
0101 int ievnum = -1, const Pythia8::Info* pyinfo = 0,
0102 Pythia8::Settings* pyset = 0, bool append = false,
0103 GenParticle* rootParticle = 0, int iBarcode = -1) {
0104 return fill_next_event(pyev, &evt, ievnum, pyinfo, pyset,
0105 append, rootParticle, iBarcode); }
0106
0107 bool fill_next_event( Pythia8::Event& pyev, GenEvent* evt,
0108 int ievnum = -1, const Pythia8::Info* pyinfo = 0,
0109 Pythia8::Settings* pyset = 0, bool append = false,
0110 GenParticle* rootParticle = 0, int iBarcode = -1);
0111
0112
0113 bool print_inconsistency() const {return m_print_inconsistency;}
0114 bool free_parton_exception() const {return m_free_parton_exception;}
0115 bool free_parton_warnings() const {return m_free_parton_exception;}
0116 bool convert_gluon_to_0() const {return m_convert_gluon_to_0;}
0117 bool store_pdf() const {return m_store_pdf;}
0118 bool store_proc() const {return m_store_proc;}
0119 bool store_xsec() const {return m_store_xsec;}
0120 bool store_weights() const {return m_store_weights;}
0121
0122
0123 void set_print_inconsistency(bool b = true) {m_print_inconsistency = b;}
0124 void set_free_parton_exception(bool b = true) {m_free_parton_exception = b;}
0125 void set_free_parton_warnings(bool b = true) {m_free_parton_exception = b;}
0126 void set_convert_gluon_to_0(bool b = false) {m_convert_gluon_to_0 = b;}
0127 void set_store_pdf(bool b = true) {m_store_pdf = b;}
0128 void set_store_proc(bool b = true) {m_store_proc = b;}
0129 void set_store_xsec(bool b = true) {m_store_xsec = b;}
0130 void set_store_weights(bool b = true) {m_store_weights = b;}
0131
0132 private:
0133
0134
0135
0136 bool warning(const Pythia8::Info* pyinfo, std::string loc,
0137 std::string message, std::string extraInfo = "") {
0138 if (pyinfo != nullptr)
0139 pyinfo->loggerPtr->warningMsg(loc, message, extraInfo);
0140 else if ( print_inconsistency() )
0141 std::cout << "Warning in " << loc << ": " << message << extraInfo
0142 << std::endl;
0143 return false;
0144 }
0145
0146
0147 virtual bool fill_next_event( GenEvent* ) { return 0; }
0148 virtual void write_event( const GenEvent* ) {;}
0149
0150
0151 Pythia8ToHepMC( const Pythia8ToHepMC& ) : IO_BaseClass() {;}
0152
0153
0154 int m_internal_event_number;
0155 bool m_print_inconsistency, m_free_parton_exception, m_convert_gluon_to_0,
0156 m_store_pdf, m_store_proc, m_store_xsec, m_store_weights;
0157
0158 };
0159
0160
0161
0162
0163
0164
0165
0166 inline bool Pythia8ToHepMC::fill_next_event(Pythia8::Event& pyev,
0167 GenEvent* evt, int ievnum, const Pythia8::Info* pyinfo,
0168 Pythia8::Settings* pyset, bool append, GenParticle* rootParticle,
0169 int iBarcode) {
0170
0171
0172 if (evt == nullptr) return warning(pyinfo,
0173 "Pythia8ToHepMC::fill_next_event", "passed null event");
0174
0175
0176 if (!append) {
0177 if (ievnum >= 0) {
0178 evt->set_event_number(ievnum);
0179 m_internal_event_number = ievnum;
0180 } else {
0181 evt->set_event_number(m_internal_event_number);
0182 ++m_internal_event_number;
0183 }
0184 }
0185
0186
0187 double momFac = HepMC::Units::conversion_factor(HepMC::Units::GEV,
0188 evt->momentum_unit());
0189 double lenFac = HepMC::Units::conversion_factor(HepMC::Units::MM,
0190 evt->length_unit());
0191
0192
0193 int iStart = 1;
0194 int newBarcode = 0;
0195 if (append) {
0196 if (rootParticle == nullptr) return warning(pyinfo,
0197 "Pythia8ToHepMC::fill_next_event",
0198 "passed null root particle in append mode");
0199 iStart = 2;
0200 newBarcode = (iBarcode > -1) ? iBarcode : evt->particles_size();
0201
0202 GenVertex* prod_vtx0 = new GenVertex();
0203 prod_vtx0->add_particle_in( rootParticle );
0204 evt->add_vertex( prod_vtx0 );
0205 }
0206
0207
0208 if ( pyinfo && pyinfo->hiInfo ) {
0209 HepMC::HeavyIon ion;
0210 ion.set_Ncoll_hard(pyinfo->hiInfo->nCollND());
0211 ion.set_Ncoll(pyinfo->hiInfo->nCollTot());
0212 ion.set_Npart_proj(pyinfo->hiInfo->nAbsProj() +
0213 pyinfo->hiInfo->nDiffProj());
0214 ion.set_Npart_targ(pyinfo->hiInfo->nAbsTarg() +
0215 pyinfo->hiInfo->nDiffTarg());
0216 ion.set_impact_parameter(pyinfo->hiInfo->b());
0217 evt->set_heavy_ion(ion);
0218 }
0219
0220
0221
0222 std::vector<GenParticle*> hepevt_particles( pyev.size() );
0223 for (int i = iStart; i < pyev.size(); ++i) {
0224
0225
0226 hepevt_particles[i] = new GenParticle(
0227 FourVector( momFac * pyev[i].px(), momFac * pyev[i].py(),
0228 momFac * pyev[i].pz(), momFac * pyev[i].e() ),
0229 pyev[i].id(), pyev[i].statusHepMC() );
0230 if (iBarcode != 0) ++newBarcode;
0231 hepevt_particles[i]->suggest_barcode( (append) ? newBarcode : i );
0232 hepevt_particles[i]->set_generated_mass( momFac * pyev[i].m() );
0233
0234
0235 int colType = pyev[i].colType();
0236 if (colType == 1 || colType == 2)
0237 hepevt_particles[i]->set_flow(1, pyev[i].col());
0238 if (colType == -1 || colType == 2)
0239 hepevt_particles[i]->set_flow(2, pyev[i].acol());
0240 }
0241
0242
0243
0244 if (!append)
0245 evt->set_beam_particles( hepevt_particles[1], hepevt_particles[2] );
0246
0247
0248
0249
0250 for (int i = iStart; i < pyev.size(); ++i) {
0251 GenParticle* p = hepevt_particles[i];
0252
0253
0254 std::vector<int> mothers = pyev[i].motherList();
0255 unsigned int imother = 0;
0256 int mother = -1;
0257 if ( !mothers.empty() ) mother = mothers[imother];
0258 GenVertex* prod_vtx = p->production_vertex();
0259 while ( !prod_vtx && mother > 0 ) {
0260 prod_vtx = (append && mother == 1) ? rootParticle->end_vertex()
0261 : hepevt_particles[mother]->end_vertex();
0262 if (prod_vtx) prod_vtx->add_particle_out( p );
0263 mother = ( ++imother < mothers.size() ) ? mothers[imother] : -1;
0264 }
0265
0266
0267
0268 FourVector prod_pos( lenFac * pyev[i].xProd(), lenFac * pyev[i].yProd(),
0269 lenFac * pyev[i].zProd(), lenFac * pyev[i].tProd() );
0270 if ( !prod_vtx && ( mothers.size() > 0 || prod_pos != FourVector() ) ) {
0271 prod_vtx = new GenVertex();
0272 prod_vtx->add_particle_out( p );
0273 evt->add_vertex( prod_vtx );
0274 }
0275
0276
0277 if ( prod_vtx && prod_vtx->position() == FourVector() )
0278 prod_vtx->set_position( prod_pos );
0279
0280
0281 imother = 0;
0282 mother = -1;
0283 if ( !mothers.empty() ) mother = mothers[imother];
0284 while ( prod_vtx && mother > 0 ) {
0285
0286
0287 GenParticle* ppp = (append && mother == 1) ? rootParticle
0288 : hepevt_particles[mother];
0289 if ( !ppp->end_vertex() ) {
0290 prod_vtx->add_particle_in( ppp );
0291 } else if (ppp->end_vertex() != prod_vtx ) {
0292
0293
0294
0295
0296
0297 if ( (pyev[i].statusAbs() == 43 || pyev[i].statusAbs() == 51
0298 || pyev[i].statusAbs() == 53) && mother >= 1) break;
0299
0300
0301
0302
0303 warning(pyinfo, "Pythia8ToHepMC::fill_next_event",
0304 "inconsistent mother/daugher information in Pythia8 event",
0305 "i = " + Pythia8::toString(i) + " mother = " +
0306 Pythia8::toString(mother));
0307 }
0308
0309
0310 mother = ( ++imother < mothers.size() ) ? mothers[imother] : -1;
0311 }
0312 }
0313
0314
0315 bool doHadr = (pyset == 0) ? m_free_parton_exception
0316 : pyset->flag("HadronLevel:all") && pyset->flag("HadronLevel:Hadronize");
0317
0318
0319
0320
0321 for (int i = iStart; i < pyev.size(); ++i) {
0322 if ( hepevt_particles[i]->end_vertex() == nullptr &&
0323 hepevt_particles[i]->production_vertex() == nullptr ) {
0324 warning(pyinfo, "Pythia8ToHepMC::fill_next_event"
0325 "found orphan particle", "i = " + Pythia8::toString(i));
0326 GenVertex* prod_vtx = new GenVertex();
0327 prod_vtx->add_particle_out( hepevt_particles[i] );
0328 evt->add_vertex( prod_vtx );
0329 }
0330
0331
0332 if ( doHadr && m_free_parton_exception ) {
0333 int pdg_tmp = hepevt_particles[i]->pdg_id();
0334 if ( (abs(pdg_tmp) <= 6 || pdg_tmp == 21)
0335 && !hepevt_particles[i]->end_vertex() )
0336 throw PartonEndVertexException(i, pdg_tmp);
0337 }
0338 }
0339
0340
0341 if (append) return true;
0342
0343
0344
0345 if (m_store_pdf && pyinfo != 0) {
0346 int id1pdf = pyinfo->id1pdf();
0347 int id2pdf = pyinfo->id2pdf();
0348 if ( m_convert_gluon_to_0 ) {
0349 if (id1pdf == 21) id1pdf = 0;
0350 if (id2pdf == 21) id2pdf = 0;
0351 }
0352
0353
0354 evt->set_pdf_info( PdfInfo( id1pdf, id2pdf, pyinfo->x1pdf(),
0355 pyinfo->x2pdf(), pyinfo->QFac(), pyinfo->pdf1(), pyinfo->pdf2() ) );
0356 }
0357
0358
0359 if (m_store_proc && pyinfo != 0) {
0360 evt->set_signal_process_id( pyinfo->code() );
0361 evt->set_mpi( pyinfo->nMPI() );
0362 evt->set_event_scale( pyinfo->QRen() );
0363 if (evt->alphaQED() <= 0) evt->set_alphaQED( pyinfo->alphaEM() );
0364 if (evt->alphaQCD() <= 0) evt->set_alphaQCD( pyinfo->alphaS() );
0365 }
0366
0367
0368
0369 if (m_store_xsec && pyinfo != 0) {
0370 HepMC::GenCrossSection xsec;
0371 xsec.set_cross_section( pyinfo->sigmaGen() * 1e9,
0372 pyinfo->sigmaErr() * 1e9);
0373 evt->set_cross_section(xsec);
0374
0375 std::vector<double> xsecVec = pyinfo->weightContainerPtr->getTotalXsec();
0376 if (xsecVec.size() > 0) {
0377 xsec.set_cross_section(xsecVec[0]*1e9);
0378 evt->set_cross_section(xsec);
0379 }
0380 }
0381
0382 if (m_store_weights && pyinfo != 0) {
0383 for (int iweight = 0; iweight < pyinfo->numberOfWeights();
0384 ++iweight) {
0385 std::string name = pyinfo->weightNameByIndex(iweight);
0386 double value = pyinfo->weightValueByIndex(iweight);
0387 evt->weights()[name] = value;
0388 }
0389 }
0390
0391
0392 return true;
0393
0394 }
0395
0396
0397
0398 }
0399
0400 namespace Pythia8 {
0401
0402
0403
0404
0405
0406
0407
0408
0409 class Pythia8ToHepMC : public HepMC::Pythia8ToHepMC {
0410
0411 public:
0412
0413
0414 enum OutputType { none, ascii2 };
0415
0416
0417 typedef HepMC::GenEvent GenEvent;
0418 typedef shared_ptr<GenEvent> EventPtr;
0419 typedef HepMC::IO_GenEvent Writer;
0420 typedef shared_ptr<Writer> WriterPtr;
0421
0422
0423 Pythia8ToHepMC() {}
0424
0425
0426 Pythia8ToHepMC(string filename, OutputType ft = ascii2) {
0427 setNewFile(filename, ft);
0428 }
0429
0430
0431 bool setNewFile(string filename, OutputType ft = ascii2) {
0432 switch ( ft ) {
0433 case ascii2:
0434 writerPtr = make_shared<HepMC::IO_GenEvent>(filename);
0435 break;
0436 case none:
0437 writerPtr = nullptr;
0438 break;
0439 }
0440 return writerPtr != nullptr;
0441 }
0442
0443
0444
0445 bool fillNextEvent(Pythia & pythia) {
0446 geneve = make_shared<GenEvent>();
0447 return fill_next_event(pythia, *geneve);
0448 }
0449
0450
0451 void writeEvent() {
0452 writerPtr->write_event(&*geneve);
0453 }
0454
0455
0456
0457
0458 bool writeNextEvent(Pythia & pythia) {
0459 if ( !fillNextEvent(pythia) ) return false;
0460 writeEvent();
0461 return true;
0462 }
0463
0464
0465 GenEvent & event() {
0466 return *geneve;
0467 }
0468
0469
0470 EventPtr getEventPtr() {
0471 return geneve;
0472 }
0473
0474
0475 Writer & output() {
0476 return *writerPtr;
0477 }
0478
0479
0480 WriterPtr outputPtr() {
0481 return writerPtr;
0482 }
0483
0484
0485 void setXSec(double xsec, double xsecerr) {
0486 HepMC::GenCrossSection xs;
0487 xs.set_cross_section(xsec, xsecerr);
0488 geneve->set_cross_section(xs);
0489 }
0490
0491
0492 void setWeights(const vector<double> & wv) {
0493 if ( wv.size() != weightNames.size() )
0494 geneve->weights() = wv;
0495 else
0496 for ( int i= 0, N = wv.size(); i < N; ++i )
0497 geneve->weights()[weightNames[i]] = wv[i];
0498 }
0499
0500
0501 void setWeightNames(const vector<string> &wnv) {
0502 weightNames = wnv;
0503 }
0504
0505
0506 void setPdfInfo(int id1, int id2, double x1, double x2,
0507 double scale, double xf1, double xf2,
0508 int pdf1 = 0, int pdf2 = 0) {
0509 HepMC::PdfInfo pdf(id1, id2, x1, x2, scale, xf1, xf2, pdf1, pdf2);
0510 geneve->set_pdf_info(pdf);
0511 }
0512
0513 private:
0514
0515
0516 EventPtr geneve = nullptr;
0517
0518
0519 WriterPtr writerPtr = nullptr;
0520
0521
0522 vector<string> weightNames;
0523
0524 };
0525
0526 }
0527
0528 #endif