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
00181
00182
00183 if( params.exists( "reweightGen" ) )
00184 fReweightUserHook = new PtHatReweightUserHook();
00185
00186
00187
00188 if ( params.exists("jetMatching") )
00189 {
00190 edm::ParameterSet jmParams =
00191 params.getUntrackedParameter<edm::ParameterSet>("jetMatching");
00192 fJetMatchingHook = new JetMatchingHook( jmParams, &pythia->info );
00193 }
00194
00195
00196
00197 if ( params.exists("emissionVeto") )
00198 {
00199 fEmissionVetoHook = new EmissionVetoHook(0);
00200 pythia->setUserHooksPtr( fEmissionVetoHook );
00201 }
00202
00203 int NHooks=0;
00204 if(fReweightUserHook) NHooks++;
00205 if(fJetMatchingHook) NHooks++;
00206 if(fEmissionVetoHook) NHooks++;
00207 if(NHooks > 1)
00208 throw edm::Exception(edm::errors::Configuration,"Pythia8Interface")
00209 <<" Too many User Hooks. \n Please choose one from: reweightGen, jetMatching, emissionVeto \n";
00210
00211 if(fReweightUserHook) pythia->setUserHooksPtr(fReweightUserHook);
00212 if(fJetMatchingHook) pythia->setUserHooksPtr(fJetMatchingHook);
00213 if(fEmissionVetoHook) pythia->setUserHooksPtr(fEmissionVetoHook);
00214 }
00215
00216
00217 Pythia8Hadronizer::~Pythia8Hadronizer()
00218 {
00219
00220
00221 if(fEmissionVetoHook) {delete fEmissionVetoHook; fEmissionVetoHook=0;}
00222 }
00223
00224
00225 bool Pythia8Hadronizer::readSettings( int )
00226 {
00227 for ( ParameterCollector::const_iterator line = parameters.begin();
00228 line != parameters.end(); ++line ) {
00229 if (line->find("Random:") != std::string::npos)
00230 throw cms::Exception("PythiaError") << "Attempted to set random number "
00231 "using Pythia commands. Please use " "the RandomNumberGeneratorService."
00232 << std::endl;
00233
00234 if (!pythia->readString(*line)) throw cms::Exception("PythiaError")
00235 << "Pythia 8 did not accept \""
00236 << *line << "\"." << std::endl;
00237 }
00238
00239 if ( pythiaPylistVerbosity > 10 ) {
00240 if ( pythiaPylistVerbosity == 11 || pythiaPylistVerbosity == 13 )
00241 pythia->settings.listAll();
00242 if ( pythiaPylistVerbosity == 12 || pythiaPylistVerbosity == 13 )
00243 pythia->particleData.listAll();
00244 }
00245
00246 return true;
00247 }
00248
00249
00250 bool Pythia8Hadronizer::initializeForInternalPartons()
00251 {
00252
00253 pythiaEvent = &pythia->event;
00254
00255 if ( fInitialState == PP )
00256 {
00257 pythia->init(2212, 2212, comEnergy);
00258 }
00259 else if ( fInitialState == PPbar )
00260 {
00261 pythia->init(2212, -2212, comEnergy);
00262 }
00263 else if ( fInitialState == ElectronPositron )
00264 {
00265 pythia->init(11, -11, comEnergy);
00266 }
00267 else
00268 {
00269
00270 throw edm::Exception(edm::errors::Configuration,"Pythia8Interface")
00271 <<" UNKNOWN INITIAL STATE. \n The allowed initial states are: PP, PPbar, ElectronPositron \n";
00272 }
00273
00274 pythia->settings.listChanged();
00275
00276 return true;
00277 }
00278
00279
00280 bool Pythia8Hadronizer::initializeForExternalPartons()
00281 {
00282
00283 std::cout << "Initializing for external partons" << std::endl;
00284
00285 pythiaEvent = &pythia->event;
00286
00287 if(LHEInputFileName != string()) {
00288
00289 cout << endl;
00290 cout << "LHE Input File Name = " << LHEInputFileName << endl;
00291 cout << endl;
00292 pythia->init(LHEInputFileName);
00293
00294 } else {
00295
00296 lhaUP.reset(new LHAupLesHouches());
00297 lhaUP->loadRunInfo(lheRunInfo());
00298 pythia->init(lhaUP.get());
00299
00300 }
00301
00302
00303
00304 if ( fJetMatchingHook )
00305 {
00306
00307
00308 fJetMatchingHook->init ( lheRunInfo() );
00309 }
00310
00311 return true;
00312 }
00313
00314
00315 #if 0
00316
00317 static int getStatus(const HepMC::GenParticle *p)
00318 {
00319 int status = p->status();
00320 if (status > 0)
00321 return status;
00322 else if (status > -30 && status < 0)
00323 return 3;
00324 else
00325 return 2;
00326 }
00327 #endif
00328
00329
00330 bool Pythia8Hadronizer::declareStableParticles(const std::vector<int> &pdgIds)
00331 {
00332 for ( size_t i=0; i<pdgIds.size(); i++ )
00333 {
00334
00335
00336
00337
00338
00339
00340 int PyID = pdgIds[i];
00341 std::ostringstream pyCard ;
00342 pyCard << PyID <<":mayDecay=false";
00343 pythia->readString( pyCard.str() );
00344
00345
00346
00347
00348 }
00349
00350
00351 decayer->readString("ProcessLevel:all = off");
00352 decayer->init();
00353
00354 return true;
00355 }
00356
00357
00358 bool Pythia8Hadronizer::declareSpecialSettings( const std::vector<std::string> settings )
00359 {
00360 for ( unsigned int iss=0; iss<settings.size(); iss++ )
00361 {
00362 if ( settings[iss].find("QED-brem-off") == std::string::npos ) continue;
00363 pythia->readString( "TimeShower:QEDshowerByL=off" );
00364 }
00365
00366 return true;
00367 }
00368
00369
00370 void Pythia8Hadronizer::statistics()
00371 {
00372 pythia->statistics();
00373
00374 double xsec = pythia->info.sigmaGen();
00375 xsec *= 1.0e9;
00376 runInfo().setInternalXSec(xsec);
00377 }
00378
00379
00380 bool Pythia8Hadronizer::generatePartonsAndHadronize()
00381 {
00382 if (!pythia->next()) return false;
00383
00384 event().reset(new HepMC::GenEvent);
00385 toHepMC.fill_next_event(*pythiaEvent, event().get());
00386
00387 return true;
00388 }
00389
00390
00391 bool Pythia8Hadronizer::hadronize()
00392 {
00393 if(LHEInputFileName == string()) lhaUP->loadEvent(lheEvent());
00394
00395 if ( fJetMatchingHook )
00396 {
00397 fJetMatchingHook->resetMatchingStatus();
00398 fJetMatchingHook->beforeHadronization( lheEvent() );
00399 }
00400
00401 bool py8next = pythia->next();
00402
00403 if (!py8next)
00404 {
00405 lheEvent()->count( lhef::LHERunInfo::kSelected );
00406 event().reset();
00407 return false;
00408 }
00409
00410
00411
00412 lheEvent()->count( lhef::LHERunInfo::kAccepted );
00413
00414 event().reset(new HepMC::GenEvent);
00415 toHepMC.fill_next_event(*pythiaEvent, event().get());
00416
00417 return true;
00418 }
00419
00420
00421 bool Pythia8Hadronizer::decay()
00422 {
00423 return true;
00424 }
00425
00426
00427 bool Pythia8Hadronizer::residualDecay()
00428 {
00429
00430 int NPartsBeforeDecays = pythiaEvent->size();
00431 int NPartsAfterDecays = event().get()->particles_size();
00432 int NewBarcode = NPartsAfterDecays;
00433
00434 for ( int ipart=NPartsAfterDecays; ipart>NPartsBeforeDecays; ipart-- )
00435 {
00436
00437 HepMC::GenParticle* part = event().get()->barcode_to_particle( ipart );
00438
00439 if ( part->status() == 1 )
00440 {
00441 decayer->event.reset();
00442 Particle py8part( part->pdg_id(), 93, 0, 0, 0, 0, 0, 0,
00443 part->momentum().x(),
00444 part->momentum().y(),
00445 part->momentum().z(),
00446 part->momentum().t(),
00447 part->generated_mass() );
00448 HepMC::GenVertex* ProdVtx = part->production_vertex();
00449 py8part.vProd( ProdVtx->position().x(), ProdVtx->position().y(),
00450 ProdVtx->position().z(), ProdVtx->position().t() );
00451 py8part.tau( (decayer->particleData).tau0( part->pdg_id() ) );
00452 decayer->event.append( py8part );
00453 int nentries = decayer->event.size();
00454 if ( !decayer->event[nentries-1].mayDecay() ) continue;
00455 decayer->next();
00456 int nentries1 = decayer->event.size();
00457
00458 if ( nentries1 <= nentries ) continue;
00459
00460 part->set_status(2);
00461
00462 Particle& py8daughter = decayer->event[nentries];
00463 HepMC::GenVertex* DecVtx = new HepMC::GenVertex( HepMC::FourVector(py8daughter.xProd(),
00464 py8daughter.yProd(),
00465 py8daughter.zProd(),
00466 py8daughter.tProd()) );
00467
00468 DecVtx->add_particle_in( part );
00469
00470
00471 HepMC::FourVector pmom( py8daughter.px(), py8daughter.py(), py8daughter.pz(), py8daughter.e() );
00472
00473 HepMC::GenParticle* daughter =
00474 new HepMC::GenParticle( pmom, py8daughter.id(), 1 );
00475
00476 NewBarcode++;
00477 daughter->suggest_barcode( NewBarcode );
00478 DecVtx->add_particle_out( daughter );
00479
00480 for ( ipart=nentries+1; ipart<nentries1; ipart++ )
00481 {
00482 py8daughter = decayer->event[ipart];
00483 HepMC::FourVector pmomN( py8daughter.px(), py8daughter.py(), py8daughter.pz(), py8daughter.e() );
00484 HepMC::GenParticle* daughterN =
00485 new HepMC::GenParticle( pmomN, py8daughter.id(), 1 );
00486 NewBarcode++;
00487 daughterN->suggest_barcode( NewBarcode );
00488 DecVtx->add_particle_out( daughterN );
00489 }
00490
00491 event().get()->add_vertex( DecVtx );
00492
00493 }
00494 }
00495
00496 return true;
00497 }
00498
00499
00500 void Pythia8Hadronizer::finalizeEvent()
00501 {
00502 bool lhe = lheEvent() != 0;
00503
00504 event()->set_signal_process_id(pythia->info.code());
00505 event()->set_event_scale(pythia->info.pTHat());
00506
00507
00508
00509
00510
00511
00512 if (event()->alphaQED() <= 0)
00513 event()->set_alphaQED( pythia->info.alphaEM() );
00514 if (event()->alphaQCD() <= 0)
00515 event()->set_alphaQCD( pythia->info.alphaS() );
00516
00517 HepMC::GenCrossSection xsec;
00518 xsec.set_cross_section( pythia->info.sigmaGen() * 1e9,
00519 pythia->info.sigmaErr() * 1e9);
00520 event()->set_cross_section(xsec);
00521
00522
00523
00524
00525
00526
00527
00528
00529 int id1 = pythia->info.id1();
00530 int id2 = pythia->info.id2();
00531 if (id1 == 21) id1 = 0;
00532 if (id2 == 21) id2 = 0;
00533 double x1 = pythia->info.x1();
00534 double x2 = pythia->info.x2();
00535
00536 double Q = pythia->info.QFac();
00537 double pdf1 = pythia->info.pdf1() / pythia->info.x1();
00538 double pdf2 = pythia->info.pdf2() / pythia->info.x2();
00539 event()->set_pdf_info(HepMC::PdfInfo(id1,id2,x1,x2,Q,pdf1,pdf2));
00540
00541
00542
00543 if (lhe && std::abs(lheRunInfo()->getHEPRUP()->IDWTUP) == 4)
00544
00545 event()->weights().push_back( pythia->info.weight() * 1.0e9 );
00546 else
00547 event()->weights().push_back( pythia->info.weight() );
00548
00549
00550
00551 eventInfo().reset( new GenEventInfoProduct( event().get() ) );
00552
00553
00554
00555
00556 if (!lhe) {
00557 eventInfo()->setBinningValues(std::vector<double>(1, pythia->info.pTHat()));
00558 }
00559
00560
00561
00562 if (maxEventsToPrint > 0 &&
00563 (pythiaPylistVerbosity || pythiaHepMCVerbosity)) {
00564 maxEventsToPrint--;
00565 if (pythiaPylistVerbosity) {
00566 pythia->info.list(std::cout);
00567 pythia->event.list(std::cout);
00568 }
00569
00570 if (pythiaHepMCVerbosity) {
00571 std::cout << "Event process = "
00572 << pythia->info.code() << "\n"
00573 << "----------------------" << std::endl;
00574 event()->print();
00575 }
00576 }
00577 }
00578
00579
00580 typedef edm::GeneratorFilter<Pythia8Hadronizer, ExternalDecayDriver> Pythia8GeneratorFilter;
00581 DEFINE_FWK_MODULE(Pythia8GeneratorFilter);
00582
00583
00584 typedef edm::HadronizerFilter<Pythia8Hadronizer, ExternalDecayDriver> Pythia8HadronizerFilter;
00585 DEFINE_FWK_MODULE(Pythia8HadronizerFilter);