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