File indexing completed on 2025-01-18 10:06:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef Pythia8_HepMC3_H
0012 #define Pythia8_HepMC3_H
0013
0014 #ifdef Pythia8_HepMC2_H
0015 #error Cannot include HepMC3.h if HepMC2.h has already been included.
0016 #endif
0017
0018 #include <vector>
0019 #include "Pythia8/Pythia.h"
0020 #include "Pythia8/HIInfo.h"
0021 #include "HepMC3/GenVertex.h"
0022 #include "HepMC3/GenParticle.h"
0023 #include "HepMC3/GenEvent.h"
0024 #include "HepMC3/WriterAscii.h"
0025 #include "HepMC3/WriterAsciiHepMC2.h"
0026 #include "HepMC3/GenHeavyIon.h"
0027 #include "HepMC3/GenPdfInfo.h"
0028
0029 namespace HepMC3 {
0030
0031
0032
0033 class Pythia8ToHepMC3 {
0034
0035 public:
0036
0037
0038 Pythia8ToHepMC3(): m_internal_event_number(0), m_print_inconsistency(true),
0039 m_free_parton_warnings(true), m_crash_on_problem(false),
0040 m_convert_gluon_to_0(false), m_store_pdf(true), m_store_proc(true),
0041 m_store_xsec(true), m_store_weights(true) {}
0042 virtual ~Pythia8ToHepMC3() {}
0043
0044
0045 bool fill_next_event( Pythia8::Pythia& pythia, GenEvent* evt,
0046 int ievnum = -1 ) { return fill_next_event( pythia.event, evt,
0047 ievnum, &pythia.info, &pythia.settings); }
0048 bool fill_next_event( Pythia8::Pythia& pythia, GenEvent& evt) {
0049 return fill_next_event( pythia, &evt); }
0050
0051
0052 bool fill_next_event( Pythia8::Event& pyev, GenEvent&evt, int ievnum = -1,
0053 const Pythia8::Info* pyinfo = 0, Pythia8::Settings* pyset = 0) {
0054 return fill_next_event(pyev, &evt, ievnum, pyinfo, pyset); }
0055 bool fill_next_event( Pythia8::Event& pyev, GenEvent* evt, int ievnum = -1,
0056 const Pythia8::Info* pyinfo = 0, Pythia8::Settings* pyset = 0) {
0057
0058
0059 if (!evt) {
0060 std::cerr << "Pythia8ToHepMC3::fill_next_event error - "
0061 << "passed null event." << std::endl;
0062 return false;
0063 }
0064
0065
0066 if ( ievnum >= 0 ) {
0067 evt->set_event_number(ievnum);
0068 m_internal_event_number = ievnum;
0069 }
0070 else {
0071 evt->set_event_number(m_internal_event_number);
0072 ++m_internal_event_number;
0073 }
0074
0075
0076 evt->set_units(Units::GEV,Units::MM);
0077
0078
0079 if ( pyinfo && pyinfo->hiInfo ) {
0080 auto ion = make_shared<HepMC3::GenHeavyIon>();
0081 ion->Ncoll_hard = pyinfo->hiInfo->nCollNDTot();
0082 ion->Ncoll = pyinfo->hiInfo->nAbsProj() +
0083 pyinfo->hiInfo->nDiffProj() +
0084 pyinfo->hiInfo->nAbsTarg() +
0085 pyinfo->hiInfo->nDiffTarg() -
0086 pyinfo->hiInfo->nCollND() -
0087 pyinfo->hiInfo->nCollDD();
0088 ion->Npart_proj = pyinfo->hiInfo->nAbsProj() +
0089 pyinfo->hiInfo->nDiffProj();
0090 ion->Npart_targ = pyinfo->hiInfo->nAbsTarg() +
0091 pyinfo->hiInfo->nDiffTarg();
0092 ion->impact_parameter = pyinfo->hiInfo->b();
0093 evt->set_heavy_ion(ion);
0094 }
0095
0096
0097 std::vector<GenParticlePtr> hepevt_particles;
0098 hepevt_particles.reserve( pyev.size() );
0099 for(int i = 0; i < pyev.size(); ++i) {
0100 hepevt_particles.push_back( std::make_shared<GenParticle>(
0101 FourVector( pyev[i].px(), pyev[i].py(), pyev[i].pz(), pyev[i].e() ),
0102 pyev[i].id(), pyev[i].statusHepMC() ) );
0103 hepevt_particles[i]->set_generated_mass( pyev[i].m() );
0104 }
0105
0106
0107 std::vector<GenVertexPtr> vertex_cache;
0108 for (int i = 3; i < pyev.size(); ++i) {
0109 std::vector<int> mothers = pyev[i].motherList();
0110 if (mothers.size()) {
0111 GenVertexPtr prod_vtx = hepevt_particles[mothers[0]]->end_vertex();
0112 if (!prod_vtx) {
0113 prod_vtx = make_shared<GenVertex>();
0114 vertex_cache.push_back(prod_vtx);
0115 for (unsigned int j = 0; j < mothers.size(); ++j)
0116 prod_vtx->add_particle_in( hepevt_particles[mothers[j]] );
0117 }
0118 FourVector prod_pos( pyev[i].xProd(), pyev[i].yProd(),pyev[i].zProd(),
0119 pyev[i].tProd() );
0120
0121
0122 if (!prod_pos.is_zero() && prod_vtx->position().is_zero())
0123 prod_vtx->set_position( prod_pos );
0124 prod_vtx->add_particle_out( hepevt_particles[i] );
0125 }
0126 }
0127
0128
0129 evt->reserve( hepevt_particles.size(), vertex_cache.size() );
0130
0131
0132 vector<GenParticlePtr> beam_particles;
0133 beam_particles.push_back(hepevt_particles[1]);
0134 beam_particles.push_back(hepevt_particles[2]);
0135
0136
0137 evt->add_tree( beam_particles );
0138
0139 for (int i = 0; i < pyev.size(); ++i) {
0140
0141
0142 int colType = pyev[i].colType();
0143 if (colType == -1 ||colType == 1 || colType == 2) {
0144 int flow1 = 0, flow2 = 0;
0145 if (colType == 1 || colType == 2) flow1 = pyev[i].col();
0146 if (colType == -1 || colType == 2) flow2 = pyev[i].acol();
0147 hepevt_particles[i]->add_attribute("flow1",
0148 make_shared<IntAttribute>(flow1));
0149 hepevt_particles[i]->add_attribute("flow2",
0150 make_shared<IntAttribute>(flow2));
0151 }
0152 }
0153
0154
0155 bool doHadr = (pyset == 0) ? m_free_parton_warnings
0156 : pyset->flag("HadronLevel:all") && pyset->flag("HadronLevel:Hadronize");
0157
0158
0159
0160
0161 for (int i = 1; i < pyev.size(); ++i) {
0162
0163
0164
0165
0166 if ( !hepevt_particles[i] ) {
0167 std::cerr << "hanging particle " << i << std::endl;
0168 GenVertexPtr prod_vtx = make_shared<GenVertex>();
0169 prod_vtx->add_particle_out( hepevt_particles[i] );
0170 evt->add_vertex(prod_vtx);
0171 }
0172
0173
0174 if ( doHadr && m_free_parton_warnings ) {
0175 if ( hepevt_particles[i]->pid() == 21
0176 && !hepevt_particles[i]->end_vertex() ) {
0177 std::cerr << "gluon without end vertex " << i << std::endl;
0178 if ( m_crash_on_problem ) exit(1);
0179 }
0180 if ( std::abs(hepevt_particles[i]->pid()) <= 6
0181 && !hepevt_particles[i]->end_vertex() ) {
0182 std::cerr << "quark without end vertex " << i << std::endl;
0183 if ( m_crash_on_problem ) exit(1);
0184 }
0185 }
0186 }
0187
0188
0189
0190 if (m_store_pdf && pyinfo != 0) {
0191 int id1pdf = pyinfo->id1pdf();
0192 int id2pdf = pyinfo->id2pdf();
0193 if ( m_convert_gluon_to_0 ) {
0194 if (id1pdf == 21) id1pdf = 0;
0195 if (id2pdf == 21) id2pdf = 0;
0196 }
0197
0198
0199 GenPdfInfoPtr pdfinfo = make_shared<GenPdfInfo>();
0200 pdfinfo->set(id1pdf, id2pdf, pyinfo->x1pdf(), pyinfo->x2pdf(),
0201 pyinfo->QFac(), pyinfo->pdf1(), pyinfo->pdf2() );
0202 evt->set_pdf_info( pdfinfo );
0203 }
0204
0205
0206 if (m_store_proc && pyinfo != 0) {
0207 evt->add_attribute("signal_process_id",
0208 std::make_shared<IntAttribute>( pyinfo->code()));
0209 evt->add_attribute("event_scale",
0210 std::make_shared<DoubleAttribute>(pyinfo->QRen()));
0211 evt->add_attribute("alphaQCD",
0212 std::make_shared<DoubleAttribute>(pyinfo->alphaS()));
0213 evt->add_attribute("alphaQED",
0214 std::make_shared<DoubleAttribute>(pyinfo->alphaEM()));
0215 }
0216
0217
0218 if (m_store_weights && pyinfo != 0) {
0219 evt->weights().clear();
0220 for (int iWeight = 0; iWeight < pyinfo->numberOfWeights(); ++iWeight)
0221 evt->weights().push_back(pyinfo->weightValueByIndex(iWeight));
0222 }
0223
0224
0225 if (m_store_xsec && pyinfo != 0) {
0226
0227
0228
0229 GenCrossSectionPtr xsec = make_shared<GenCrossSection>();
0230 evt->set_cross_section(xsec);
0231 xsec->set_cross_section( pyinfo->sigmaGen() * 1e9,
0232 pyinfo->sigmaErr() * 1e9);
0233
0234 vector<double> xsecVec = pyinfo->weightContainerPtr->getTotalXsec();
0235 if (xsecVec.size() > 0) {
0236 for (unsigned int iXsec = 0; iXsec < xsecVec.size(); ++iXsec) {
0237 xsec->set_xsec(iXsec, xsecVec[iXsec]*1e9);
0238 }
0239 }
0240 }
0241
0242
0243 return true;
0244 }
0245
0246
0247 bool print_inconsistency() const { return m_print_inconsistency; }
0248 bool free_parton_warnings() const { return m_free_parton_warnings; }
0249 bool crash_on_problem() const { return m_crash_on_problem; }
0250 bool convert_gluon_to_0() const { return m_convert_gluon_to_0; }
0251 bool store_pdf() const { return m_store_pdf; }
0252 bool store_proc() const { return m_store_proc; }
0253 bool store_xsec() const { return m_store_xsec; }
0254 bool store_weights() const { return m_store_weights; }
0255
0256
0257 void set_print_inconsistency(bool b = true) { m_print_inconsistency = b; }
0258 void set_free_parton_warnings(bool b = true) { m_free_parton_warnings = b; }
0259 void set_crash_on_problem(bool b = false) { m_crash_on_problem = b; }
0260 void set_convert_gluon_to_0(bool b = false) { m_convert_gluon_to_0 = b; }
0261 void set_store_pdf(bool b = true) { m_store_pdf = b; }
0262 void set_store_proc(bool b = true) { m_store_proc = b; }
0263 void set_store_xsec(bool b = true) { m_store_xsec = b; }
0264 void set_store_weights(bool b = true) { m_store_weights = b; }
0265
0266 private:
0267
0268
0269 virtual bool fill_next_event( GenEvent* ) { return 0; }
0270 virtual void write_event( const GenEvent* ) {}
0271
0272
0273 Pythia8ToHepMC3( const Pythia8ToHepMC3& ) {}
0274
0275
0276 int m_internal_event_number;
0277 bool m_print_inconsistency, m_free_parton_warnings, m_crash_on_problem,
0278 m_convert_gluon_to_0, m_store_pdf, m_store_proc, m_store_xsec,
0279 m_store_weights;
0280
0281 };
0282
0283
0284
0285 }
0286
0287 namespace Pythia8 {
0288
0289
0290
0291
0292
0293
0294
0295
0296 class Pythia8ToHepMC : public HepMC3::Pythia8ToHepMC3 {
0297
0298 public:
0299
0300
0301
0302 enum OutputType { none, ascii2, ascii3 };
0303
0304
0305 typedef HepMC3::GenEvent GenEvent;
0306 typedef shared_ptr<GenEvent> EventPtr;
0307 typedef HepMC3::Writer Writer;
0308 typedef shared_ptr<Writer> WriterPtr;
0309
0310
0311 Pythia8ToHepMC() : runinfo(make_shared<HepMC3::GenRunInfo>()) {}
0312
0313
0314 Pythia8ToHepMC(string filename, OutputType ft = ascii3)
0315 : runinfo(make_shared<HepMC3::GenRunInfo>()) {
0316 setNewFile(filename, ft);
0317 }
0318
0319
0320 bool setNewFile(string filename, OutputType ft = ascii3) {
0321 switch ( ft ) {
0322 case ascii3:
0323 writerPtr = make_shared<HepMC3::WriterAscii>(filename);
0324 break;
0325 case ascii2:
0326 writerPtr = make_shared<HepMC3::WriterAsciiHepMC2>(filename);
0327 break;
0328 case none:
0329 break;
0330 }
0331 return writerPtr != nullptr;
0332 }
0333
0334
0335
0336 bool fillNextEvent(Pythia & pythia) {
0337 geneve = make_shared<HepMC3::GenEvent>(runinfo);
0338 if (runinfo->weight_names().size() == 0)
0339 setWeightNames(pythia.info.weightNameVector());
0340 return fill_next_event(pythia, *geneve);
0341 }
0342
0343
0344 void writeEvent() {
0345 writerPtr->write_event(*geneve);
0346 }
0347
0348
0349
0350
0351 bool writeNextEvent(Pythia & pythia) {
0352 if ( !fillNextEvent(pythia) ) return false;
0353 writeEvent();
0354 return !writerPtr->failed();
0355 }
0356
0357
0358 GenEvent & event() {
0359 return *geneve;
0360 }
0361
0362
0363 EventPtr getEventPtr() {
0364 return geneve;
0365 }
0366
0367
0368 Writer & output() {
0369 return *writerPtr;
0370 }
0371
0372
0373 WriterPtr outputPtr() {
0374 return writerPtr;
0375 }
0376
0377
0378 void setXSec(double xsec, double xsecerr) {
0379 auto xsecptr = geneve->cross_section();
0380 if ( !xsecptr ) {
0381 xsecptr = make_shared<HepMC3::GenCrossSection>();
0382 geneve->set_cross_section(xsecptr);
0383 }
0384 xsecptr->set_cross_section(xsec, xsecerr);
0385 }
0386
0387
0388 void setWeights(const vector<double> & wv) {
0389 geneve->weights() = wv;
0390 }
0391
0392
0393 void setWeightNames(const vector<string> &wnv) {
0394 runinfo->set_weight_names(wnv);
0395 }
0396
0397
0398 void setPdfInfo(int id1, int id2, double x1, double x2,
0399 double scale, double xf1, double xf2,
0400 int pdf1 = 0, int pdf2 = 0) {
0401 auto pdf = make_shared<HepMC3::GenPdfInfo>();
0402 pdf->set(id1, id2, x1, x2, scale, xf1, xf2, pdf1, pdf2);
0403 geneve->set_pdf_info(pdf);
0404 }
0405
0406
0407
0408 template<class T>
0409 void addAtribute(const string& name, T& attribute) {
0410 shared_ptr<HepMC3::Attribute> att = make_shared<T>(attribute);
0411 geneve->add_attribute(name, att);
0412 }
0413
0414
0415 template<class T=double>
0416 void addAttribute(const string& name, double& attribute) {
0417 auto dAtt = HepMC3::DoubleAttribute(attribute);
0418 shared_ptr<HepMC3::Attribute> att =
0419 make_shared<HepMC3::DoubleAttribute>(dAtt);
0420 geneve->add_attribute(name, att);
0421 }
0422
0423
0424 void removeAttribute(const string& name) {
0425 geneve->remove_attribute(name);
0426 }
0427
0428 private:
0429
0430
0431 EventPtr geneve = nullptr;
0432
0433
0434 WriterPtr writerPtr = nullptr;
0435
0436
0437 shared_ptr<HepMC3::GenRunInfo> runinfo;
0438
0439 };
0440
0441 }
0442
0443 #endif