File indexing completed on 2025-01-18 10:06:37
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 virtual bool fill_next_event( GenEvent* ) { return 0; }
0136 virtual void write_event( const GenEvent* ) {;}
0137
0138
0139 Pythia8ToHepMC( const Pythia8ToHepMC& ) : IO_BaseClass() {;}
0140
0141
0142 int m_internal_event_number;
0143 bool m_print_inconsistency, m_free_parton_exception, m_convert_gluon_to_0,
0144 m_store_pdf, m_store_proc, m_store_xsec, m_store_weights;
0145
0146 };
0147
0148
0149
0150
0151
0152
0153
0154 inline bool Pythia8ToHepMC::fill_next_event( Pythia8::Event& pyev,
0155 GenEvent* evt, int ievnum, const Pythia8::Info* pyinfo,
0156 Pythia8::Settings* pyset, bool append, GenParticle* rootParticle,
0157 int iBarcode) {
0158
0159
0160 if (!evt) {
0161 std::cout << " Pythia8ToHepMC::fill_next_event error: passed null event."
0162 << std::endl;
0163 return 0;
0164 }
0165
0166
0167 if (!append) {
0168 if (ievnum >= 0) {
0169 evt->set_event_number(ievnum);
0170 m_internal_event_number = ievnum;
0171 } else {
0172 evt->set_event_number(m_internal_event_number);
0173 ++m_internal_event_number;
0174 }
0175 }
0176
0177
0178 double momFac = HepMC::Units::conversion_factor(HepMC::Units::GEV,
0179 evt->momentum_unit());
0180 double lenFac = HepMC::Units::conversion_factor(HepMC::Units::MM,
0181 evt->length_unit());
0182
0183
0184 int iStart = 1;
0185 int newBarcode = 0;
0186 if (append) {
0187 if (!rootParticle) {
0188 std::cout << " Pythia8ToHepMC::fill_next_event error: passed null "
0189 << "root particle in append mode." << std::endl;
0190 return 0;
0191 }
0192 iStart = 2;
0193 newBarcode = (iBarcode > -1) ? iBarcode : evt->particles_size();
0194
0195 GenVertex* prod_vtx0 = new GenVertex();
0196 prod_vtx0->add_particle_in( rootParticle );
0197 evt->add_vertex( prod_vtx0 );
0198 }
0199
0200
0201 if ( pyinfo && pyinfo->hiInfo ) {
0202 HepMC::HeavyIon ion;
0203 ion.set_Ncoll_hard(pyinfo->hiInfo->nCollNDTot());
0204 ion.set_Ncoll(pyinfo->hiInfo->nAbsProj() +
0205 pyinfo->hiInfo->nDiffProj() +
0206 pyinfo->hiInfo->nAbsTarg() +
0207 pyinfo->hiInfo->nDiffTarg() -
0208 pyinfo->hiInfo->nCollND() -
0209 pyinfo->hiInfo->nCollDD());
0210 ion.set_Npart_proj(pyinfo->hiInfo->nAbsProj() +
0211 pyinfo->hiInfo->nDiffProj());
0212 ion.set_Npart_targ(pyinfo->hiInfo->nAbsTarg() +
0213 pyinfo->hiInfo->nDiffTarg());
0214 ion.set_impact_parameter(pyinfo->hiInfo->b());
0215 evt->set_heavy_ion(ion);
0216 }
0217
0218
0219
0220 std::vector<GenParticle*> hepevt_particles( pyev.size() );
0221 for (int i = iStart; i < pyev.size(); ++i) {
0222
0223
0224 hepevt_particles[i] = new GenParticle(
0225 FourVector( momFac * pyev[i].px(), momFac * pyev[i].py(),
0226 momFac * pyev[i].pz(), momFac * pyev[i].e() ),
0227 pyev[i].id(), pyev[i].statusHepMC() );
0228 if (iBarcode != 0) ++newBarcode;
0229 hepevt_particles[i]->suggest_barcode( (append) ? newBarcode : i );
0230 hepevt_particles[i]->set_generated_mass( momFac * pyev[i].m() );
0231
0232
0233 int colType = pyev[i].colType();
0234 if (colType == 1 || colType == 2)
0235 hepevt_particles[i]->set_flow(1, pyev[i].col());
0236 if (colType == -1 || colType == 2)
0237 hepevt_particles[i]->set_flow(2, pyev[i].acol());
0238 }
0239
0240
0241
0242 if (!append)
0243 evt->set_beam_particles( hepevt_particles[1], hepevt_particles[2] );
0244
0245
0246
0247
0248 for (int i = iStart; i < pyev.size(); ++i) {
0249 GenParticle* p = hepevt_particles[i];
0250
0251
0252 std::vector<int> mothers = pyev[i].motherList();
0253 unsigned int imother = 0;
0254 int mother = -1;
0255 if ( !mothers.empty() ) mother = mothers[imother];
0256 GenVertex* prod_vtx = p->production_vertex();
0257 while ( !prod_vtx && mother > 0 ) {
0258 prod_vtx = (append && mother == 1) ? rootParticle->end_vertex()
0259 : hepevt_particles[mother]->end_vertex();
0260 if (prod_vtx) prod_vtx->add_particle_out( p );
0261 mother = ( ++imother < mothers.size() ) ? mothers[imother] : -1;
0262 }
0263
0264
0265
0266 FourVector prod_pos( lenFac * pyev[i].xProd(), lenFac * pyev[i].yProd(),
0267 lenFac * pyev[i].zProd(), lenFac * pyev[i].tProd() );
0268 if ( !prod_vtx && ( mothers.size() > 0 || prod_pos != FourVector() ) ) {
0269 prod_vtx = new GenVertex();
0270 prod_vtx->add_particle_out( p );
0271 evt->add_vertex( prod_vtx );
0272 }
0273
0274
0275 if ( prod_vtx && prod_vtx->position() == FourVector() )
0276 prod_vtx->set_position( prod_pos );
0277
0278
0279 imother = 0;
0280 mother = -1;
0281 if ( !mothers.empty() ) mother = mothers[imother];
0282 while ( prod_vtx && mother > 0 ) {
0283
0284
0285 GenParticle* ppp = (append && mother == 1) ? rootParticle
0286 : hepevt_particles[mother];
0287 if ( !ppp->end_vertex() ) {
0288 prod_vtx->add_particle_in( ppp );
0289 } else if (ppp->end_vertex() != prod_vtx ) {
0290
0291
0292
0293
0294
0295 if ( (pyev[i].statusAbs() == 43 || pyev[i].statusAbs() == 51
0296 || pyev[i].statusAbs() == 53) && mother >= 1) break;
0297
0298
0299
0300
0301 if ( m_print_inconsistency ) std::cout
0302 << " Pythia8ToHepMC::fill_next_event: inconsistent mother/daugher "
0303 << "information in Pythia8 event " << std::endl
0304 << "i = " << i << " mother = " << mother
0305 << "\n This warning can be turned off with the "
0306 << "Pythia8ToHepMC::print_inconsistency switch." << std::endl;
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() &&
0323 !hepevt_particles[i]->production_vertex() ) {
0324 std::cout << " Pythia8ToHepMC::fill_next_event error: "
0325 << "hanging particle " << i << std::endl;
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_event_scale( pyinfo->QRen() );
0362 if (evt->alphaQED() <= 0) evt->set_alphaQED( pyinfo->alphaEM() );
0363 if (evt->alphaQCD() <= 0) evt->set_alphaQCD( pyinfo->alphaS() );
0364 }
0365
0366
0367
0368 if (m_store_xsec && pyinfo != 0) {
0369 HepMC::GenCrossSection xsec;
0370 xsec.set_cross_section( pyinfo->sigmaGen() * 1e9,
0371 pyinfo->sigmaErr() * 1e9);
0372 evt->set_cross_section(xsec);
0373
0374 std::vector<double> xsecVec = pyinfo->weightContainerPtr->getTotalXsec();
0375 if (xsecVec.size() > 0) {
0376 xsec.set_cross_section(xsecVec[0]*1e9);
0377 evt->set_cross_section(xsec);
0378 }
0379 }
0380
0381 if (m_store_weights && pyinfo != 0) {
0382 for (int iweight = 0; iweight < pyinfo->numberOfWeights();
0383 ++iweight) {
0384 std::string name = pyinfo->weightNameByIndex(iweight);
0385 double value = pyinfo->weightValueByIndex(iweight);
0386 evt->weights()[name] = value;
0387 }
0388 }
0389
0390
0391 return true;
0392
0393 }
0394
0395
0396
0397 }
0398
0399 namespace Pythia8 {
0400
0401
0402
0403
0404
0405
0406
0407
0408 class Pythia8ToHepMC : public HepMC::Pythia8ToHepMC {
0409
0410 public:
0411
0412
0413 enum OutputType { none, ascii2 };
0414
0415
0416 typedef HepMC::GenEvent GenEvent;
0417 typedef shared_ptr<GenEvent> EventPtr;
0418 typedef HepMC::IO_GenEvent Writer;
0419 typedef shared_ptr<Writer> WriterPtr;
0420
0421
0422 Pythia8ToHepMC() {}
0423
0424
0425 Pythia8ToHepMC(string filename, OutputType ft = ascii2) {
0426 setNewFile(filename, ft);
0427 }
0428
0429
0430 bool setNewFile(string filename, OutputType ft = ascii2) {
0431 switch ( ft ) {
0432 case ascii2:
0433 writerPtr = make_shared<HepMC::IO_GenEvent>(filename);
0434 break;
0435 case none:
0436 writerPtr = nullptr;
0437 break;
0438 }
0439 return writerPtr != nullptr;
0440 }
0441
0442
0443
0444 bool fillNextEvent(Pythia & pythia) {
0445 geneve = make_shared<GenEvent>();
0446 return fill_next_event(pythia, *geneve);
0447 }
0448
0449
0450 void writeEvent() {
0451 writerPtr->write_event(&*geneve);
0452 }
0453
0454
0455
0456
0457 bool writeNextEvent(Pythia & pythia) {
0458 if ( !fillNextEvent(pythia) ) return false;
0459 writeEvent();
0460 return true;
0461 }
0462
0463
0464 GenEvent & event() {
0465 return *geneve;
0466 }
0467
0468
0469 EventPtr getEventPtr() {
0470 return geneve;
0471 }
0472
0473
0474 Writer & output() {
0475 return *writerPtr;
0476 }
0477
0478
0479 WriterPtr outputPtr() {
0480 return writerPtr;
0481 }
0482
0483
0484 void setXSec(double xsec, double xsecerr) {
0485 HepMC::GenCrossSection xs;
0486 xs.set_cross_section(xsec, xsecerr);
0487 geneve->set_cross_section(xs);
0488 }
0489
0490
0491 void setWeights(const vector<double> & wv) {
0492 if ( wv.size() != weightNames.size() )
0493 geneve->weights() = wv;
0494 else
0495 for ( int i= 0, N = wv.size(); i < N; ++i )
0496 geneve->weights()[weightNames[i]] = wv[i];
0497 }
0498
0499
0500 void setWeightNames(const vector<string> &wnv) {
0501 weightNames = wnv;
0502 }
0503
0504
0505 void setPdfInfo(int id1, int id2, double x1, double x2,
0506 double scale, double xf1, double xf2,
0507 int pdf1 = 0, int pdf2 = 0) {
0508 HepMC::PdfInfo pdf(id1, id2, x1, x2, scale, xf1, xf2, pdf1, pdf2);
0509 geneve->set_pdf_info(pdf);
0510 }
0511
0512 private:
0513
0514
0515 EventPtr geneve = nullptr;
0516
0517
0518 WriterPtr writerPtr = nullptr;
0519
0520
0521 vector<string> weightNames;
0522
0523 };
0524
0525 }
0526
0527 #endif