00001 #include <iostream>
00002 #include <sstream>
00003 #include <string>
00004 #include <memory>
00005 #include <stdint.h>
00006
00007 #include <HepMC/GenEvent.h>
00008 #include <HepMC/GenParticle.h>
00009
00010 #include <Pythia.h>
00011 #include <HepMCInterface.h>
00012
00013 #include "GeneratorInterface/Pythia8Interface/interface/RandomP8.h"
00014
00015 #include "GeneratorInterface/Pythia8Interface/interface/ReweightUserHooks.h"
00016
00017
00018
00019 #include "GeneratorInterface/Pythia8Interface/interface/JetMatchingHook.h"
00020
00021
00022
00023 #include "GeneratorInterface/Pythia8Interface/interface/EmissionVetoHook.h"
00024
00025 #include "FWCore/ServiceRegistry/interface/Service.h"
00026 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00027 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00028
00029 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
00030 #include "SimDataFormats/GeneratorProducts/interface/GenRunInfoProduct.h"
00031
00032 #include "GeneratorInterface/Core/interface/ParameterCollector.h"
00033 #include "GeneratorInterface/Core/interface/BaseHadronizer.h"
00034 #include "GeneratorInterface/Core/interface/GeneratorFilter.h"
00035 #include "GeneratorInterface/Core/interface/HadronizerFilter.h"
00036 #include "GeneratorInterface/Core/interface/RNDMEngineAccess.h"
00037
00038 #include "GeneratorInterface/Pythia8Interface/interface/LHAupLesHouches.h"
00039
00040 #include "HepPID/ParticleIDTranslations.hh"
00041
00042 #include "GeneratorInterface/ExternalDecays/interface/ExternalDecayDriver.h"
00043
00044 using namespace gen;
00045 using namespace Pythia8;
00046
00047 class Pythia8Hadronizer : public BaseHadronizer {
00048 public:
00049 Pythia8Hadronizer(const edm::ParameterSet ¶ms);
00050 ~Pythia8Hadronizer();
00051
00052 bool readSettings( int );
00053 bool initializeForInternalPartons();
00054 bool initializeForExternalPartons();
00055
00056 bool declareStableParticles(const std::vector<int> &pdgIds);
00057 bool declareSpecialSettings( const std::vector<std::string> );
00058
00059 void statistics();
00060
00061 bool generatePartonsAndHadronize();
00062 bool hadronize();
00063 bool decay();
00064 bool residualDecay();
00065 void finalizeEvent();
00066
00067 const char *classname() const { return "Pythia8Hadronizer"; }
00068
00069 private:
00070 ParameterCollector parameters;
00071
00073 double comEnergy;
00075 unsigned int pythiaPylistVerbosity;
00077 bool pythiaHepMCVerbosity;
00079 unsigned int maxEventsToPrint;
00080
00081 string LHEInputFileName;
00082
00083 std::auto_ptr<LHAupLesHouches> lhaUP;
00084
00085 std::auto_ptr<Pythia> pythia;
00086 std::auto_ptr<Pythia> decayer;
00087 Event* pythiaEvent;
00088 HepMC::I_Pythia8 toHepMC;
00089
00090 enum { PP, PPbar, ElectronPositron };
00091 int fInitialState ;
00092
00093 double fBeam1PZ;
00094 double fBeam2PZ;
00095
00096
00097
00098 UserHooks* fReweightUserHook;
00099
00100
00101
00102 JetMatchingHook* fJetMatchingHook;
00103
00104
00105
00106 EmissionVetoHook* fEmissionVetoHook;
00107
00108 };
00109
00110
00111 Pythia8Hadronizer::Pythia8Hadronizer(const edm::ParameterSet ¶ms) :
00112 BaseHadronizer(params),
00113 parameters(params.getParameter<edm::ParameterSet>("PythiaParameters")),
00114 comEnergy(params.getParameter<double>("comEnergy")),
00115 pythiaPylistVerbosity(params.getUntrackedParameter<int>("pythiaPylistVerbosity", 0)),
00116 pythiaHepMCVerbosity(params.getUntrackedParameter<bool>("pythiaHepMCVerbosity", false)),
00117 maxEventsToPrint(params.getUntrackedParameter<int>("maxEventsToPrint", 0)),
00118 LHEInputFileName(params.getUntrackedParameter<string>("LHEInputFileName","")),
00119 fInitialState(PP),
00120 fReweightUserHook(0),
00121 fJetMatchingHook(0),
00122 fEmissionVetoHook(0)
00123 {
00124 randomEngine = &getEngineReference();
00125
00126
00127
00128
00129
00130
00131 RandomP8* RP8 = new RandomP8();
00132
00133
00134
00135 if ( params.exists( "PPbarInitialState" ) )
00136 {
00137 if ( fInitialState == PP )
00138 {
00139 fInitialState = PPbar;
00140 edm::LogInfo("GeneratorInterface|Pythia6Interface")
00141 << "Pythia6 will be initialized for PROTON-ANTIPROTON INITIAL STATE. "
00142 << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
00143 std::cout << "Pythia6 will be initialized for PROTON-ANTIPROTON INITIAL STATE." << std::endl;
00144 std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
00145 }
00146 else
00147 {
00148
00149 }
00150 }
00151 else if ( params.exists( "ElectronPositronInitialState" ) )
00152 {
00153 if ( fInitialState == PP )
00154 {
00155 fInitialState = ElectronPositron;
00156 edm::LogInfo("GeneratorInterface|Pythia6Interface")
00157 << "Pythia6 will be initialized for ELECTRON-POSITRON INITIAL STATE. "
00158 << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
00159 std::cout << "Pythia6 will be initialized for ELECTRON-POSITRON INITIAL STATE." << std::endl;
00160 std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
00161 }
00162 else
00163 {
00164
00165 }
00166 }
00167 else if ( params.exists( "ElectronProtonInitialState" ) || params.exists( "PositronProtonInitialState" ) )
00168 {
00169
00170 throw edm::Exception(edm::errors::Configuration,"Pythia8Interface")
00171 <<" UNKNOWN INITIAL STATE. \n The allowed initial states are: PP, PPbar, ElectronPositron \n";
00172 }
00173
00174 pythia.reset(new Pythia);
00175 decayer.reset(new Pythia);
00176
00177 pythia->setRndmEnginePtr(RP8);
00178 decayer->setRndmEnginePtr(RP8);
00179
00180 if( params.exists( "SLHAFileForPythia8" ) ) {
00181 std::string slhafilenameshort = params.getParameter<string>("SLHAFileForPythia8");
00182 edm::FileInPath f1( slhafilenameshort );
00183 std::string slhafilename = f1.fullPath();
00184 std::string pythiacommandslha = std::string("SLHA:file = ") + slhafilename;
00185 pythia->readString(pythiacommandslha);
00186 for ( ParameterCollector::const_iterator line = parameters.begin();
00187 line != parameters.end(); ++line ) {
00188 if (line->find("SLHA:file") != std::string::npos)
00189 throw cms::Exception("PythiaError") << "Attempted to set SLHA file name twice, "
00190 << "using Pythia8 card SLHA:file and Pythia8Interface card SLHAFileForPythia8"
00191 << std::endl;
00192 }
00193 }
00194
00195
00196
00197 if( params.exists( "reweightGen" ) )
00198 fReweightUserHook = new PtHatReweightUserHook();
00199
00200
00201
00202 if ( params.exists("jetMatching") )
00203 {
00204 edm::ParameterSet jmParams =
00205 params.getUntrackedParameter<edm::ParameterSet>("jetMatching");
00206 fJetMatchingHook = new JetMatchingHook( jmParams, &pythia->info );
00207 }
00208
00209
00210
00211 if ( params.exists("emissionVeto") )
00212 {
00213 fEmissionVetoHook = new EmissionVetoHook(0);
00214 pythia->setUserHooksPtr( fEmissionVetoHook );
00215 }
00216
00217 int NHooks=0;
00218 if(fReweightUserHook) NHooks++;
00219 if(fJetMatchingHook) NHooks++;
00220 if(fEmissionVetoHook) NHooks++;
00221 if(NHooks > 1)
00222 throw edm::Exception(edm::errors::Configuration,"Pythia8Interface")
00223 <<" Too many User Hooks. \n Please choose one from: reweightGen, jetMatching, emissionVeto \n";
00224
00225 if(fReweightUserHook) pythia->setUserHooksPtr(fReweightUserHook);
00226 if(fJetMatchingHook) pythia->setUserHooksPtr(fJetMatchingHook);
00227 if(fEmissionVetoHook) pythia->setUserHooksPtr(fEmissionVetoHook);
00228 }
00229
00230
00231 Pythia8Hadronizer::~Pythia8Hadronizer()
00232 {
00233
00234
00235 if(fEmissionVetoHook) {delete fEmissionVetoHook; fEmissionVetoHook=0;}
00236 }
00237
00238
00239 bool Pythia8Hadronizer::readSettings( int )
00240 {
00241 for ( ParameterCollector::const_iterator line = parameters.begin();
00242 line != parameters.end(); ++line ) {
00243 if (line->find("Random:") != std::string::npos)
00244 throw cms::Exception("PythiaError") << "Attempted to set random number "
00245 "using Pythia commands. Please use " "the RandomNumberGeneratorService."
00246 << std::endl;
00247
00248 if (!pythia->readString(*line)) throw cms::Exception("PythiaError")
00249 << "Pythia 8 did not accept \""
00250 << *line << "\"." << std::endl;
00251 }
00252
00253 if ( pythiaPylistVerbosity > 10 ) {
00254 if ( pythiaPylistVerbosity == 11 || pythiaPylistVerbosity == 13 )
00255 pythia->settings.listAll();
00256 if ( pythiaPylistVerbosity == 12 || pythiaPylistVerbosity == 13 )
00257 pythia->particleData.listAll();
00258 }
00259
00260 return true;
00261 }
00262
00263
00264 bool Pythia8Hadronizer::initializeForInternalPartons()
00265 {
00266
00267 pythiaEvent = &pythia->event;
00268
00269 if ( fInitialState == PP )
00270 {
00271 pythia->init(2212, 2212, comEnergy);
00272 }
00273 else if ( fInitialState == PPbar )
00274 {
00275 pythia->init(2212, -2212, comEnergy);
00276 }
00277 else if ( fInitialState == ElectronPositron )
00278 {
00279 pythia->init(11, -11, comEnergy);
00280 }
00281 else
00282 {
00283
00284 throw edm::Exception(edm::errors::Configuration,"Pythia8Interface")
00285 <<" UNKNOWN INITIAL STATE. \n The allowed initial states are: PP, PPbar, ElectronPositron \n";
00286 }
00287
00288 pythia->settings.listChanged();
00289
00290 return true;
00291 }
00292
00293
00294 bool Pythia8Hadronizer::initializeForExternalPartons()
00295 {
00296
00297 std::cout << "Initializing for external partons" << std::endl;
00298
00299 pythiaEvent = &pythia->event;
00300
00301 if(LHEInputFileName != string()) {
00302
00303 cout << endl;
00304 cout << "LHE Input File Name = " << LHEInputFileName << endl;
00305 cout << endl;
00306 pythia->init(LHEInputFileName);
00307
00308 } else {
00309
00310 lhaUP.reset(new LHAupLesHouches());
00311 lhaUP->loadRunInfo(lheRunInfo());
00312 pythia->init(lhaUP.get());
00313
00314 }
00315
00316
00317
00318 if ( fJetMatchingHook )
00319 {
00320
00321
00322 fJetMatchingHook->init ( lheRunInfo() );
00323 }
00324
00325 return true;
00326 }
00327
00328
00329 #if 0
00330
00331 static int getStatus(const HepMC::GenParticle *p)
00332 {
00333 int status = p->status();
00334 if (status > 0)
00335 return status;
00336 else if (status > -30 && status < 0)
00337 return 3;
00338 else
00339 return 2;
00340 }
00341 #endif
00342
00343
00344 bool Pythia8Hadronizer::declareStableParticles(const std::vector<int> &pdgIds)
00345 {
00346 for ( size_t i=0; i<pdgIds.size(); i++ )
00347 {
00348
00349
00350
00351
00352
00353
00354 int PyID = pdgIds[i];
00355 std::ostringstream pyCard ;
00356 pyCard << PyID <<":mayDecay=false";
00357 pythia->readString( pyCard.str() );
00358
00359
00360
00361
00362 }
00363
00364
00365 decayer->readString("ProcessLevel:all = off");
00366 decayer->init();
00367
00368 return true;
00369 }
00370
00371
00372 bool Pythia8Hadronizer::declareSpecialSettings( const std::vector<std::string> settings )
00373 {
00374 for ( unsigned int iss=0; iss<settings.size(); iss++ )
00375 {
00376 if ( settings[iss].find("QED-brem-off") == std::string::npos ) continue;
00377 pythia->readString( "TimeShower:QEDshowerByL=off" );
00378 }
00379
00380 return true;
00381 }
00382
00383
00384 void Pythia8Hadronizer::statistics()
00385 {
00386 pythia->statistics();
00387
00388 double xsec = pythia->info.sigmaGen();
00389 xsec *= 1.0e9;
00390 runInfo().setInternalXSec(xsec);
00391 }
00392
00393
00394 bool Pythia8Hadronizer::generatePartonsAndHadronize()
00395 {
00396 if (!pythia->next()) return false;
00397
00398 event().reset(new HepMC::GenEvent);
00399 toHepMC.fill_next_event(*pythiaEvent, event().get());
00400
00401 return true;
00402 }
00403
00404
00405 bool Pythia8Hadronizer::hadronize()
00406 {
00407 if(LHEInputFileName == string()) lhaUP->loadEvent(lheEvent());
00408
00409 if ( fJetMatchingHook )
00410 {
00411 fJetMatchingHook->resetMatchingStatus();
00412 fJetMatchingHook->beforeHadronization( lheEvent() );
00413 }
00414
00415 bool py8next = pythia->next();
00416
00417 if (!py8next)
00418 {
00419 lheEvent()->count( lhef::LHERunInfo::kSelected );
00420 event().reset();
00421 return false;
00422 }
00423
00424
00425
00426 lheEvent()->count( lhef::LHERunInfo::kAccepted );
00427
00428 event().reset(new HepMC::GenEvent);
00429 toHepMC.fill_next_event(*pythiaEvent, event().get());
00430
00431 return true;
00432 }
00433
00434
00435 bool Pythia8Hadronizer::decay()
00436 {
00437 return true;
00438 }
00439
00440
00441 bool Pythia8Hadronizer::residualDecay()
00442 {
00443
00444 int NPartsBeforeDecays = pythiaEvent->size();
00445 int NPartsAfterDecays = event().get()->particles_size();
00446 int NewBarcode = NPartsAfterDecays;
00447
00448 for ( int ipart=NPartsAfterDecays; ipart>NPartsBeforeDecays; ipart-- )
00449 {
00450
00451 HepMC::GenParticle* part = event().get()->barcode_to_particle( ipart );
00452
00453 if ( part->status() == 1 )
00454 {
00455 decayer->event.reset();
00456 Particle py8part( part->pdg_id(), 93, 0, 0, 0, 0, 0, 0,
00457 part->momentum().x(),
00458 part->momentum().y(),
00459 part->momentum().z(),
00460 part->momentum().t(),
00461 part->generated_mass() );
00462 HepMC::GenVertex* ProdVtx = part->production_vertex();
00463 py8part.vProd( ProdVtx->position().x(), ProdVtx->position().y(),
00464 ProdVtx->position().z(), ProdVtx->position().t() );
00465 py8part.tau( (decayer->particleData).tau0( part->pdg_id() ) );
00466 decayer->event.append( py8part );
00467 int nentries = decayer->event.size();
00468 if ( !decayer->event[nentries-1].mayDecay() ) continue;
00469 decayer->next();
00470 int nentries1 = decayer->event.size();
00471
00472 if ( nentries1 <= nentries ) continue;
00473
00474 part->set_status(2);
00475
00476 Particle& py8daughter = decayer->event[nentries];
00477 HepMC::GenVertex* DecVtx = new HepMC::GenVertex( HepMC::FourVector(py8daughter.xProd(),
00478 py8daughter.yProd(),
00479 py8daughter.zProd(),
00480 py8daughter.tProd()) );
00481
00482 DecVtx->add_particle_in( part );
00483
00484
00485 HepMC::FourVector pmom( py8daughter.px(), py8daughter.py(), py8daughter.pz(), py8daughter.e() );
00486
00487 HepMC::GenParticle* daughter =
00488 new HepMC::GenParticle( pmom, py8daughter.id(), 1 );
00489
00490 NewBarcode++;
00491 daughter->suggest_barcode( NewBarcode );
00492 DecVtx->add_particle_out( daughter );
00493
00494 for ( ipart=nentries+1; ipart<nentries1; ipart++ )
00495 {
00496 py8daughter = decayer->event[ipart];
00497 HepMC::FourVector pmomN( py8daughter.px(), py8daughter.py(), py8daughter.pz(), py8daughter.e() );
00498 HepMC::GenParticle* daughterN =
00499 new HepMC::GenParticle( pmomN, py8daughter.id(), 1 );
00500 NewBarcode++;
00501 daughterN->suggest_barcode( NewBarcode );
00502 DecVtx->add_particle_out( daughterN );
00503 }
00504
00505 event().get()->add_vertex( DecVtx );
00506
00507 }
00508 }
00509
00510 return true;
00511 }
00512
00513
00514 void Pythia8Hadronizer::finalizeEvent()
00515 {
00516 bool lhe = lheEvent() != 0;
00517
00518 event()->set_signal_process_id(pythia->info.code());
00519 event()->set_event_scale(pythia->info.pTHat());
00520
00521
00522
00523
00524
00525
00526 if (event()->alphaQED() <= 0)
00527 event()->set_alphaQED( pythia->info.alphaEM() );
00528 if (event()->alphaQCD() <= 0)
00529 event()->set_alphaQCD( pythia->info.alphaS() );
00530
00531 HepMC::GenCrossSection xsec;
00532 xsec.set_cross_section( pythia->info.sigmaGen() * 1e9,
00533 pythia->info.sigmaErr() * 1e9);
00534 event()->set_cross_section(xsec);
00535
00536
00537
00538
00539
00540
00541
00542
00543 int id1 = pythia->info.id1();
00544 int id2 = pythia->info.id2();
00545 if (id1 == 21) id1 = 0;
00546 if (id2 == 21) id2 = 0;
00547 double x1 = pythia->info.x1();
00548 double x2 = pythia->info.x2();
00549
00550 double Q = pythia->info.QFac();
00551 double pdf1 = pythia->info.pdf1() / pythia->info.x1();
00552 double pdf2 = pythia->info.pdf2() / pythia->info.x2();
00553 event()->set_pdf_info(HepMC::PdfInfo(id1,id2,x1,x2,Q,pdf1,pdf2));
00554
00555
00556
00557 if (lhe && std::abs(lheRunInfo()->getHEPRUP()->IDWTUP) == 4)
00558
00559 event()->weights().push_back( pythia->info.weight() * 1.0e9 );
00560 else
00561 event()->weights().push_back( pythia->info.weight() );
00562
00563
00564
00565 eventInfo().reset( new GenEventInfoProduct( event().get() ) );
00566
00567
00568
00569
00570 if (!lhe) {
00571 eventInfo()->setBinningValues(std::vector<double>(1, pythia->info.pTHat()));
00572 }
00573
00574
00575
00576 if (maxEventsToPrint > 0 &&
00577 (pythiaPylistVerbosity || pythiaHepMCVerbosity)) {
00578 maxEventsToPrint--;
00579 if (pythiaPylistVerbosity) {
00580 pythia->info.list(std::cout);
00581 pythia->event.list(std::cout);
00582 }
00583
00584 if (pythiaHepMCVerbosity) {
00585 std::cout << "Event process = "
00586 << pythia->info.code() << "\n"
00587 << "----------------------" << std::endl;
00588 event()->print();
00589 }
00590 }
00591 }
00592
00593
00594 typedef edm::GeneratorFilter<Pythia8Hadronizer, ExternalDecayDriver> Pythia8GeneratorFilter;
00595 DEFINE_FWK_MODULE(Pythia8GeneratorFilter);
00596
00597
00598 typedef edm::HadronizerFilter<Pythia8Hadronizer, ExternalDecayDriver> Pythia8HadronizerFilter;
00599 DEFINE_FWK_MODULE(Pythia8HadronizerFilter);