CMS 3D CMS Logo

CMSSW_4_4_3_patch1/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/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 &params);
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 ; // pp, ppbar, or e-e+
00087 
00088         double fBeam1PZ;
00089         double fBeam2PZ;
00090 
00091         UserHooks* UserHookPointer;
00092 
00093 };
00094 
00095 
00096 Pythia8Hadronizer::Pythia8Hadronizer(const edm::ParameterSet &params) :
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     //Old code that used Pythia8 own random engine
00113     //edm::Service<edm::RandomNumberGenerator> rng;
00114     //uint32_t seed = rng->mySeed();
00115     //Pythia8::Rndm::init(seed);
00116 
00117     RandomP8* RP8 = new RandomP8();
00118 
00119     // J.Y.: the following 3 parameters are hacked "for a reason"
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         // probably need to throw on attempt to override ?
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          // probably need to throw on attempt to override ?
00151       }
00152     }
00153     else if ( params.exists( "ElectronProtonInitialState" ) || params.exists( "PositronProtonInitialState" ) )
00154     {
00155       // throw on unknown initial state !
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     //pythia->init(2212, 2212, comEnergy);
00211 
00212     if ( fInitialState == PP ) // default
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       // throw on unknown initial state !
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 //    RandomP8* RP8 = new RandomP8();
00243 
00244 //    pythia.reset(new Pythia);
00245 
00246 //    pythia->setRndmEnginePtr(RP8);
00247 
00248     pythiaEvent = &pythia->event;
00249     
00250     // readSettings();
00251 
00252 /*
00253     for(ParameterCollector::const_iterator line = parameters.begin();
00254         line != parameters.end(); ++line) {
00255         if (line->find("Random:") != std::string::npos)
00256             throw cms::Exception("PythiaError")
00257                 << "Attempted to set random number "
00258                    "using Pythia commands.  Please use "
00259                    "the RandomNumberGeneratorService."
00260                 << std::endl;
00261 
00262         if (!pythia->readString(*line))
00263             throw cms::Exception("PythiaError")
00264                 << "Pythia 8 did not accept \""
00265                 << *line << "\"." << std::endl;
00266     }
00267 
00268     if(pythiaPylistVerbosity > 10) {
00269       if(pythiaPylistVerbosity == 11 || pythiaPylistVerbosity == 13)
00270         pythia->settings.listAll();
00271       if(pythiaPylistVerbosity == 12 || pythiaPylistVerbosity == 13)
00272         pythia->particleData.listAll();
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 // naive Pythia8 HepMC status fixup
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       // FIXME: need to double check if PID's are the same in Py6 & Py8,
00314       //        because the HepPDT translation tool is actually for **Py6** 
00315       // 
00316       // well, actually it looks like Py8 operates in PDT id's rather than Py6's
00317       //
00318       // int PyID = HepPID::translatePDTtoPythia( pdgIds[i] ); 
00319       int PyID = pdgIds[i]; 
00320       std::ostringstream pyCard ;
00321       pyCard << PyID <<":mayDecay=false";
00322       pythia->readString( pyCard.str() );
00323       // alternative:
00324       // set the 2nd input argument warn=false 
00325       // - this way Py8 will NOT print warnings about unknown particle code(s)
00326       // pythia->readString( pyCard.str(), false )
00327    }
00328       
00329    // init decayer
00330    decayer->readString("ProcessLevel:all = off"); // The trick!
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(); // cross section in mb
00353     xsec *= 1.0e9; // translate to pb (CMS/Gen "convention" as of May 2009)
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       //cout << "start loading event" << endl;
00372       lhaUP->loadEvent(lheEvent());
00373       //cout << "finish loading event" << endl;
00374     }
00375 
00376     if (!pythia->next())
00377         return false;
00378 
00379     // update LHE matching statistics
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             // --> decayer->event.list(std::cout);
00425             if ( nentries1 <= nentries ) continue; // same number of paericles, no decays...
00426             
00427             part->set_status(2);
00428             
00429             Particle& py8daughter = decayer->event[nentries]; // the 1st daughter
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 ); // this will cleanup end_vertex if exists, replace with the new one
00436                                              // I presume (vtx) barcode will be given automatically
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());       //FIXME
00472 
00473   // Putting pdf info into the HepMC record
00474   // There is the overloaded pythia8 HepMCInterface method fill_next_event
00475   // that does this, but CMSSW GeneratorInterface does not fill HepMC
00476   // record according to the HepMC convention (stores f(x) instead of x*f(x)
00477   // and converts gluon PDG ID to zero). For this reason we use the
00478   // method fill_next_event (above) that does NOT this and fill pdf info here
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   // Storing weights. Will be moved to pythia8 HepMCInterface
00492   //
00493   if (lhe && std::abs(lheRunInfo()->getHEPRUP()->IDWTUP) == 4)
00494     // translate mb to pb (CMS/Gen "convention" as of May 2009)
00495     event()->weights().push_back( pythia->info.weight() * 1.0e9 );
00496   else
00497     event()->weights().push_back( pythia->info.weight() );
00498   //
00499   // Below is the weight to be used in the case of reweighting by UserHook
00500   // This is a temporary solution. It requires the explicit conversion of
00501   // the pointer. In future versions (>150) the additional factor introduced
00502   // in the UserHook will be stored by pythia. Also, putting the weights
00503   // into the HepMC record will be made in the pythia8 HepMCInterface
00504   //
00505   if(useUserHook)
00506     event()->weights().push_back(1./((PtHatReweightUserHook*)UserHookPointer)->getFactor());
00507 
00508   // now create the GenEventInfo product from the GenEvent and fill
00509   // the missing pieces
00510   eventInfo().reset( new GenEventInfoProduct( event().get() ) );
00511 
00512   // in pythia pthat is used to subdivide samples into different bins
00513   // in LHE mode the binning is done by the external ME generator
00514   // which is likely not pthat, so only filling it for Py6 internal mode
00515   if (!lhe) {
00516     eventInfo()->setBinningValues(std::vector<double>(1, pythia->info.pTHat()));
00517   }
00518 
00519   //******** Verbosity ********
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);