CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/GeneratorInterface/Pythia8Interface/src/Pythia8Hadronizer.cc

Go to the documentation of this file.
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 // PS matchning prototype
00018 //
00019 #include "GeneratorInterface/Pythia8Interface/interface/JetMatchingHook.h"
00020 
00021 // Emission Veto Hook
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 &params);
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 ; // pp, ppbar, or e-e+
00092 
00093     double fBeam1PZ;
00094     double fBeam2PZ;
00095 
00096     // Reweight user hook
00097     //
00098     UserHooks* fReweightUserHook;
00099         
00100     // PS matching protot6ype
00101     //
00102     JetMatchingHook* fJetMatchingHook;
00103         
00104     // Emission Veto Hook
00105     //
00106     EmissionVetoHook* fEmissionVetoHook;
00107 
00108 };
00109 
00110 
00111 Pythia8Hadronizer::Pythia8Hadronizer(const edm::ParameterSet &params) :
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   //Old code that used Pythia8 own random engine
00127   //edm::Service<edm::RandomNumberGenerator> rng;
00128   //uint32_t seed = rng->mySeed();
00129   //Pythia8::Rndm::init(seed);
00130 
00131   RandomP8* RP8 = new RandomP8();
00132 
00133   // J.Y.: the following 3 parameters are hacked "for a reason"
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       // probably need to throw on attempt to override ?
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        // probably need to throw on attempt to override ?
00165     }
00166   }
00167   else if ( params.exists( "ElectronProtonInitialState" ) || params.exists( "PositronProtonInitialState" ) )
00168   {
00169     // throw on unknown initial state !
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   // Reweight user hook
00182   //
00183   if( params.exists( "reweightGen" ) )
00184     fReweightUserHook = new PtHatReweightUserHook();
00185 
00186   // PS matching prototype
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   // Emission veto
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 // do we need to delete UserHooks/JetMatchingHook here ???
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 ) // default
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     // throw on unknown initial state !
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   // PS matching prototype
00303   //
00304   if ( fJetMatchingHook ) 
00305   {
00306     // matcher will be init as well, inside init(...)
00307     //
00308     fJetMatchingHook->init ( lheRunInfo() );
00309   }
00310 
00311     return true;
00312 }
00313 
00314 
00315 #if 0
00316 // naive Pythia8 HepMC status fixup
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     // FIXME: need to double check if PID's are the same in Py6 & Py8,
00335     //        because the HepPDT translation tool is actually for **Py6** 
00336     // 
00337     // well, actually it looks like Py8 operates in PDT id's rather than Py6's
00338     //
00339     // int PyID = HepPID::translatePDTtoPythia( pdgIds[i] ); 
00340     int PyID = pdgIds[i]; 
00341     std::ostringstream pyCard ;
00342     pyCard << PyID <<":mayDecay=false";
00343     pythia->readString( pyCard.str() );
00344     // alternative:
00345     // set the 2nd input argument warn=false 
00346     // - this way Py8 will NOT print warnings about unknown particle code(s)
00347     // pythia->readString( pyCard.str(), false )
00348   }
00349       
00350   // init decayer
00351   decayer->readString("ProcessLevel:all = off"); // The trick!
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(); // cross section in mb
00375   xsec *= 1.0e9; // translate to pb (CMS/Gen "convention" as of May 2009)
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   // if (!pythia->next())
00403   if (!py8next)
00404   {
00405     lheEvent()->count( lhef::LHERunInfo::kSelected );
00406     event().reset();
00407     return false;
00408   }
00409 
00410   // update LHE matching statistics
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       // --> decayer->event.list(std::cout);
00458       if ( nentries1 <= nentries ) continue; //same number of particles, no decays...
00459             
00460       part->set_status(2);
00461             
00462       Particle& py8daughter = decayer->event[nentries]; // the 1st daughter
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 ); // this will cleanup end_vertex if exists, replace with the new one
00469                                        // I presume (vtx) barcode will be given automatically
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());       //FIXME
00506 
00507   //cout.precision(10);
00508   //cout << " pt = " << pythia->info.pTHat() << " weights = "
00509   //     << pythia->info.weight() << " "
00510   //     << fReweightUserHook->biasedSelectionWeight() << endl;
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   // Putting pdf info into the HepMC record
00523   // There is the overloaded pythia8 HepMCInterface method fill_next_event
00524   // that does this, but CMSSW GeneratorInterface does not fill HepMC
00525   // record according to the HepMC convention (stores f(x) instead of x*f(x)
00526   // and converts gluon PDG ID to zero). For this reason we use the
00527   // method fill_next_event (above) that does NOT this and fill pdf info here
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   //double Q = pythia->info.QRen();
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   // Storing weights. Will be moved to pythia8 HepMCInterface
00542   //
00543   if (lhe && std::abs(lheRunInfo()->getHEPRUP()->IDWTUP) == 4)
00544     // translate mb to pb (CMS/Gen "convention" as of May 2009)
00545     event()->weights().push_back( pythia->info.weight() * 1.0e9 );
00546   else
00547     event()->weights().push_back( pythia->info.weight() );
00548 
00549   // now create the GenEventInfo product from the GenEvent and fill
00550   // the missing pieces
00551   eventInfo().reset( new GenEventInfoProduct( event().get() ) );
00552 
00553   // in pythia pthat is used to subdivide samples into different bins
00554   // in LHE mode the binning is done by the external ME generator
00555   // which is likely not pthat, so only filling it for Py6 internal mode
00556   if (!lhe) {
00557     eventInfo()->setBinningValues(std::vector<double>(1, pythia->info.pTHat()));
00558   }
00559 
00560   //******** Verbosity ********
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);