CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/GeneratorInterface/Herwig6Interface/plugins/Herwig6Hadronizer.cc

Go to the documentation of this file.
00001 #include <cstring>
00002 #include <sstream>
00003 #include <string>
00004 #include <vector>
00005 #include <memory>
00006 #include <map>
00007 #include <set>
00008 
00009 #include <boost/shared_ptr.hpp>
00010 #include <boost/algorithm/string/classification.hpp>
00011 #include <boost/algorithm/string/split.hpp>
00012 
00013 #include <HepMC/GenEvent.h>
00014 #include <HepMC/GenParticle.h>
00015 #include <HepMC/GenVertex.h>
00016 #include <HepMC/PdfInfo.h>
00017 #include <HepMC/HerwigWrapper6_4.h>
00018 #include <HepMC/HEPEVT_Wrapper.h>
00019 #include <HepMC/IO_HERWIG.h>
00020 #include "HepPID/ParticleIDTranslations.hh"
00021 
00022 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00023 
00024 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
00025 #include "SimDataFormats/GeneratorProducts/interface/GenRunInfoProduct.h"
00026 
00027 #include "SimDataFormats/GeneratorProducts/interface/LesHouches.h"
00028 #include "SimDataFormats/GeneratorProducts/interface/LHECommonBlocks.h"
00029 
00030 #include "GeneratorInterface/Core/interface/ParameterCollector.h"
00031 #include "GeneratorInterface/Core/interface/BaseHadronizer.h"
00032 #include "GeneratorInterface/Core/interface/GeneratorFilter.h"
00033 #include "GeneratorInterface/Core/interface/HadronizerFilter.h"
00034 
00035 #include "GeneratorInterface/LHEInterface/interface/LHEEvent.h"
00036 
00037 #include "GeneratorInterface/Herwig6Interface/interface/Herwig6Instance.h"
00038 #include "GeneratorInterface/Herwig6Interface/interface/herwig.h"
00039 
00040 #include "DataFormats/Math/interface/LorentzVector.h"
00041 
00042 extern "C" {
00043   void hwuidt_(int *iopt, int *ipdg, int *iwig, char nwig[8]);
00044   double hwualf_(int *mode, double* scale);
00045   double hwuaem_(double* scale);
00046 }
00047 
00048 // helpers
00049 namespace {
00050         static inline bool call_hwmsct()
00051         {
00052                 int result;
00053                 hwmsct(&result);
00054                 return result;
00055         }
00056 
00057         static int pdgToHerwig(int ipdg, char *nwig)
00058         {
00059                 int iopt = 1;
00060                 int iwig = 0;
00061                 hwuidt_(&iopt, &ipdg, &iwig, nwig);
00062                 return ipdg ? iwig : 0;
00063         }
00064 
00065         static bool markStable(int pdgId)
00066         {
00067                 char nwig[9] = "        ";
00068                 if (!pdgToHerwig(pdgId, nwig))
00069                         return false;
00070                 hwusta(nwig, 1);
00071                 return true;
00072         }
00073 }
00074 
00075 class Herwig6Hadronizer : public gen::BaseHadronizer,
00076                           public gen::Herwig6Instance {
00077     public:
00078         Herwig6Hadronizer(const edm::ParameterSet &params);
00079         ~Herwig6Hadronizer();
00080 
00081         void setSLHAFromHeader(const std::vector<std::string> &lines);
00082         bool initialize(const lhef::HEPRUP *heprup);
00083 
00084         bool readSettings( int );
00085         
00086         // bool initializeForInternalPartons() { return initialize(0); }
00087         // bool initializeForExternalPartons() { return initialize(lheRunInfo()->getHEPRUP()); }
00088 
00089         bool initializeForInternalPartons();
00090         bool initializeForExternalPartons() { return initializeForInternalPartons(); }
00091 
00092         bool declareStableParticles( const std::vector<int> &pdgIds);
00093         bool declareSpecialSettings( const std::vector<std::string> );
00094 
00095         void statistics();
00096 
00097 
00098         bool generatePartonsAndHadronize() { return hadronize(); }
00099         bool hadronize();
00100         bool decay();
00101         bool residualDecay();
00102         void finalizeEvent();
00103 
00104         const char *classname() const { return "Herwig6Hadronizer"; }
00105 
00106     private:
00107         void clear();
00108 
00109         int pythiaStatusCode(const HepMC::GenParticle *p) const;
00110         void pythiaStatusCodes();
00111 
00112         virtual void upInit();
00113         virtual void upEvnt();
00114 
00115         HepMC::IO_HERWIG                conv;
00116         bool                            needClear;
00117         bool                            externalPartons;
00118 
00119         gen::ParameterCollector         parameters;
00120         int                             herwigVerbosity;
00121         int                             hepmcVerbosity;
00122         int                             maxEventsToPrint;
00123         bool                            printCards;
00124         bool                            emulatePythiaStatusCodes;
00125         double                          comEnergy;
00126         bool                            useJimmy;
00127         bool                            doMPInteraction;
00128         int                             numTrials;
00129         bool                            fConvertToPDG;  // convert PIDs 
00130 
00131         bool                            readMCatNLOfile;
00132 
00133 };
00134 
00135 extern "C" {
00136         void hwwarn_(const char *method, int *id);
00137         void setherwpdf_(void);
00138         void mysetpdfpath_(const char *path);
00139 } // extern "C"
00140 
00141 Herwig6Hadronizer::Herwig6Hadronizer(const edm::ParameterSet &params) :
00142         BaseHadronizer(params),
00143         needClear(false),
00144         parameters(params.getParameter<edm::ParameterSet>("HerwigParameters")),
00145         herwigVerbosity(params.getUntrackedParameter<int>("herwigVerbosity", 0)),
00146         hepmcVerbosity(params.getUntrackedParameter<int>("hepmcVerbosity", 0)),
00147         maxEventsToPrint(params.getUntrackedParameter<int>("maxEventsToPrint", 0)),
00148         printCards(params.getUntrackedParameter<bool>("printCards", false)),
00149         emulatePythiaStatusCodes(params.getUntrackedParameter<bool>("emulatePythiaStatusCodes", false)),
00150         comEnergy(params.getParameter<double>("comEnergy")),
00151         useJimmy(params.getParameter<bool>("useJimmy")),
00152         doMPInteraction(params.getParameter<bool>("doMPInteraction")),
00153         numTrials(params.getUntrackedParameter<int>("numTrialsMPI", 100)),
00154         readMCatNLOfile(false)
00155 {
00156   
00157   fConvertToPDG = false;
00158   if ( params.exists( "doPDGConvert" ) )
00159     fConvertToPDG = params.getParameter<bool>("doPDGConvert");
00160 }
00161 
00162 Herwig6Hadronizer::~Herwig6Hadronizer()
00163 {
00164         clear();
00165 }
00166 
00167 void Herwig6Hadronizer::clear()
00168 {
00169         if (!needClear)
00170                 return;
00171 
00172         // teminate elementary process
00173         call(hwefin);
00174         if (useJimmy)
00175                 call(jmefin);
00176 
00177         needClear = false;
00178 }
00179 
00180 void Herwig6Hadronizer::setSLHAFromHeader(
00181                                 const std::vector<std::string> &lines)
00182 {
00183         std::set<std::string> blocks;
00184         std::string block;
00185         for(std::vector<std::string>::const_iterator iter = lines.begin();
00186             iter != lines.end(); ++iter) {
00187                 std::string line = *iter;
00188                 std::transform(line.begin(), line.end(),
00189                                line.begin(), (int(*)(int))std::toupper);
00190                 std::string::size_type pos = line.find('#');
00191                 if (pos != std::string::npos)
00192                         line.resize(pos);
00193 
00194                 if (line.empty())
00195                         continue;
00196 
00197                 if (!boost::algorithm::is_space()(line[0])) {
00198                         std::vector<std::string> tokens;
00199                         boost::split(tokens, line,
00200                                      boost::algorithm::is_space(),
00201                                      boost::token_compress_on);
00202                         if (!tokens.size())
00203                                 continue;
00204                         block.clear();
00205                         if (tokens.size() < 2)
00206                                 continue;
00207                         if (tokens[0] == "BLOCK")
00208                                 block = tokens[1];
00209                         else if (tokens[0] == "DECAY")
00210                                 block = "DECAY";
00211 
00212                         if (block.empty())
00213                                 continue;
00214 
00215                         if (!blocks.count(block)) {
00216                                 blocks.insert(block);
00217                                 edm::LogWarning("Generator|Herwig6Hadronzier")
00218                                         << "Unsupported SLHA block \"" << block
00219                                         << "\".  It will be ignored."
00220                                         << std::endl;
00221                         }
00222                 }
00223         }
00224 }
00225 
00226 bool Herwig6Hadronizer:: readSettings( int key )
00227 {
00228 
00229    clear();
00230    const lhef::HEPRUP* heprup = lheRunInfo()->getHEPRUP();
00231    externalPartons = ( heprup != 0 );
00232    
00233    if ( key == 0 && externalPartons ) return false;
00234    if ( key > 0 && !externalPartons ) return false;
00235 
00236    std::ostringstream info;
00237    info << "---------------------------------------------------\n"; 
00238    info << "Taking in settinsg for Herwig6Hadronizer for "
00239         << (externalPartons ? "external" : "internal") << " partons\n";
00240    info << "---------------------------------------------------\n";
00241 
00242    info << "   Herwig verbosity level         = " << herwigVerbosity << "\n";
00243    info << "   HepMC verbosity                = " << hepmcVerbosity << "\n";
00244    info << "   Number of events to be printed = " << maxEventsToPrint << "\n";
00245 
00246    // Call hwudat to set up HERWIG block data
00247    hwudat();
00248 
00249    // Setting basic parameters
00250    if (externalPartons) {
00251                 hwproc.PBEAM1 = heprup->EBMUP.first;
00252                 hwproc.PBEAM2 = heprup->EBMUP.second;
00253                 pdgToHerwig(heprup->IDBMUP.first, hwbmch.PART1);
00254                 pdgToHerwig(heprup->IDBMUP.second, hwbmch.PART2);
00255    } 
00256    else 
00257    {
00258                 hwproc.PBEAM1 = 0.5 * comEnergy;
00259                 hwproc.PBEAM2 = 0.5 * comEnergy;
00260                 pdgToHerwig(2212, hwbmch.PART1);
00261                 pdgToHerwig(2212, hwbmch.PART2);
00262    }
00263 
00264    if (useJimmy) 
00265    {
00266                 info << "   HERWIG will be using JIMMY for UE/MI.\n";
00267                 jmparm.MSFLAG = 1;
00268                 if (doMPInteraction)
00269                         info << "   JIMMY trying to generate multiple interactions.\n";
00270    }
00271 
00272 
00273    // set the IPROC already here... needed for VB pairs
00274 
00275    bool iprocFound=false;
00276         
00277    for(gen::ParameterCollector::const_iterator line = parameters.begin();
00278                                                line != parameters.end(); ++line) 
00279    {
00280           if(!strcmp((line->substr(0,5)).c_str(),"IPROC")) {
00281             if (!give(*line))
00282               throw edm::Exception(edm::errors::Configuration)
00283                 << "Herwig 6 did not accept the following: \""
00284                 << *line << "\"." << std::endl;
00285             else iprocFound=true;
00286           }
00287    }
00288         
00289    if (!iprocFound && !externalPartons)
00290           throw edm::Exception(edm::errors::Configuration)
00291             << "You have to define the process with IPROC."  << std::endl;
00292 
00293    // initialize other common blocks ...
00294    call(hwigin); // default init
00295    
00296    hwevnt.MAXER = 100000000;    // O(inf)
00297    hwpram.LWSUD = 0;            // don't write Sudakov form factors
00298    hwdspn.LWDEC = 0;            // don't write three/four body decays
00299                                 // (no fort.77 and fort.88 ...)
00300         // init LHAPDF glue
00301         std::memset(hwprch.AUTPDF, ' ', sizeof hwprch.AUTPDF);
00302         for(unsigned int i = 0; i < 2; i++) {
00303                 hwpram.MODPDF[i] = -111;
00304                 std::memcpy(hwprch.AUTPDF[i], "HWLHAPDF", 8);
00305         }
00306 
00307         hwevnt.MAXPR = maxEventsToPrint;
00308         hwpram.IPRINT = herwigVerbosity;
00309 //      hwprop.RMASS[6] = 175.0;        //FIXME
00310 
00311         if (printCards) {
00312                 info << "\n";
00313                 info << "------------------------------------\n";
00314                 info << "Reading HERWIG parameters\n";
00315                 info << "------------------------------------\n";
00316     
00317         }
00318         for(gen::ParameterCollector::const_iterator line = parameters.begin();
00319             line != parameters.end(); ++line) {
00320                 if (printCards)
00321                         info << "   " << *line << "\n";
00322                 if (!give(*line))
00323                         throw edm::Exception(edm::errors::Configuration)
00324                                 << "Herwig 6 did not accept the following: \""
00325                                 << *line << "\"." << std::endl;
00326         }
00327 
00328         if (printCards)
00329                 info << "\n";
00330 
00331         if (externalPartons) {
00332                 std::vector<std::string> slha =
00333                                 lheRunInfo()->findHeader("slha");
00334                 if (!slha.empty())
00335                         setSLHAFromHeader(slha);
00336         }
00337 
00338         needClear = true;
00339 
00340         std::pair<int, int> pdfs(-1, -1);
00341         if (externalPartons)
00342                 pdfs = lheRunInfo()->pdfSetTranslation();
00343 
00344         if (hwpram.MODPDF[0] != -111 || hwpram.MODPDF[1] != -111) {
00345                 for(unsigned int i = 0; i < 2; i++)
00346                         if (hwpram.MODPDF[i] == -111)
00347                                 hwpram.MODPDF[i] = -1;
00348 
00349                 if (pdfs.first != -1 || pdfs.second != -1)
00350                         edm::LogError("Generator|Herwig6Hadronzier")
00351                                 << "Both external Les Houches event and "
00352                                    "config file specify a PDF set.  "
00353                                    "User PDF will override external one."
00354                                 << std::endl;
00355 
00356                 pdfs.first = hwpram.MODPDF[0] != -111 ? hwpram.MODPDF[0] : -1;
00357                 pdfs.second = hwpram.MODPDF[1] != -111 ? hwpram.MODPDF[1] : -1;
00358         }
00359 
00360         hwpram.MODPDF[0] = pdfs.first;
00361         hwpram.MODPDF[1] = pdfs.second;
00362 
00363         if (externalPartons)
00364                 hwproc.IPROC = -1;
00365 
00366    edm::LogInfo(info.str());
00367 
00368    return true;
00369 
00370 }
00371 
00372 bool Herwig6Hadronizer::initializeForInternalPartons()
00373 {
00374 
00375    if (useJimmy) call(jimmin);
00376    
00377    call(hwuinc);
00378 
00379    // initialize HERWIG event generation
00380    call(hweini);
00381 
00382    if (useJimmy) call(jminit);
00383 
00384    return true;
00385 
00386 }
00387 
00388 
00389 bool Herwig6Hadronizer::initialize(const lhef::HEPRUP *heprup)
00390 {
00391         clear();
00392 
00393         externalPartons = (heprup != 0);
00394 
00395         std::ostringstream info;
00396         info << "---------------------------------------------------\n"; 
00397         info << "Initializing Herwig6Hadronizer for "
00398              << (externalPartons ? "external" : "internal") << " partons\n";
00399         info << "---------------------------------------------------\n";
00400 
00401         info << "   Herwig verbosity level         = " << herwigVerbosity << "\n";
00402         info << "   HepMC verbosity                = " << hepmcVerbosity << "\n";
00403         info << "   Number of events to be printed = " << maxEventsToPrint << "\n";
00404 
00405         // Call hwudat to set up HERWIG block data
00406         hwudat();
00407 
00408         // Setting basic parameters
00409         if (externalPartons) {
00410                 hwproc.PBEAM1 = heprup->EBMUP.first;
00411                 hwproc.PBEAM2 = heprup->EBMUP.second;
00412                 pdgToHerwig(heprup->IDBMUP.first, hwbmch.PART1);
00413                 pdgToHerwig(heprup->IDBMUP.second, hwbmch.PART2);
00414         } else {
00415                 hwproc.PBEAM1 = 0.5 * comEnergy;
00416                 hwproc.PBEAM2 = 0.5 * comEnergy;
00417                 pdgToHerwig(2212, hwbmch.PART1);
00418                 pdgToHerwig(2212, hwbmch.PART2);
00419         }
00420 
00421         if (useJimmy) {
00422                 info << "   HERWIG will be using JIMMY for UE/MI.\n";
00423                 jmparm.MSFLAG = 1;
00424                 if (doMPInteraction)
00425                         info << "   JIMMY trying to generate multiple interactions.\n";
00426         }
00427 
00428         // set the IPROC already here... needed for VB pairs
00429 
00430         bool iprocFound=false;
00431         
00432         for(gen::ParameterCollector::const_iterator line = parameters.begin();
00433             line != parameters.end(); ++line) {
00434           if(!strcmp((line->substr(0,5)).c_str(),"IPROC")) {
00435             if (!give(*line))
00436               throw edm::Exception(edm::errors::Configuration)
00437                 << "Herwig 6 did not accept the following: \""
00438                 << *line << "\"." << std::endl;
00439             else iprocFound=true;
00440           }
00441         }
00442         
00443         if (!iprocFound && !externalPartons)
00444           throw edm::Exception(edm::errors::Configuration)
00445             << "You have to define the process with IPROC."  << std::endl;
00446 
00447         // initialize other common blocks ...
00448         call(hwigin);
00449         hwevnt.MAXER = 100000000;       // O(inf)
00450         hwpram.LWSUD = 0;               // don't write Sudakov form factors
00451         hwdspn.LWDEC = 0;               // don't write three/four body decays
00452                                         // (no fort.77 and fort.88 ...)
00453 
00454         // init LHAPDF glue
00455 
00456         std::memset(hwprch.AUTPDF, ' ', sizeof hwprch.AUTPDF);
00457         for(unsigned int i = 0; i < 2; i++) {
00458                 hwpram.MODPDF[i] = -111;
00459                 std::memcpy(hwprch.AUTPDF[i], "HWLHAPDF", 8);
00460         }
00461 
00462         if (useJimmy)
00463                 call(jimmin);
00464 
00465         hwevnt.MAXPR = maxEventsToPrint;
00466         hwpram.IPRINT = herwigVerbosity;
00467 //      hwprop.RMASS[6] = 175.0;        //FIXME
00468 
00469         if (printCards) {
00470                 info << "\n";
00471                 info << "------------------------------------\n";
00472                 info << "Reading HERWIG parameters\n";
00473                 info << "------------------------------------\n";
00474     
00475         }
00476         for(gen::ParameterCollector::const_iterator line = parameters.begin();
00477             line != parameters.end(); ++line) {
00478                 if (printCards)
00479                         info << "   " << *line << "\n";
00480                 if (!give(*line))
00481                         throw edm::Exception(edm::errors::Configuration)
00482                                 << "Herwig 6 did not accept the following: \""
00483                                 << *line << "\"." << std::endl;
00484         }
00485 
00486         if (printCards)
00487                 info << "\n";
00488 
00489         if (externalPartons) {
00490                 std::vector<std::string> slha =
00491                                 lheRunInfo()->findHeader("slha");
00492                 if (!slha.empty())
00493                         setSLHAFromHeader(slha);
00494         }
00495 
00496         needClear = true;
00497 
00498         std::pair<int, int> pdfs(-1, -1);
00499         if (externalPartons)
00500                 pdfs = lheRunInfo()->pdfSetTranslation();
00501 
00502         if (hwpram.MODPDF[0] != -111 || hwpram.MODPDF[1] != -111) {
00503                 for(unsigned int i = 0; i < 2; i++)
00504                         if (hwpram.MODPDF[i] == -111)
00505                                 hwpram.MODPDF[i] = -1;
00506 
00507                 if (pdfs.first != -1 || pdfs.second != -1)
00508                         edm::LogError("Generator|Herwig6Hadronzier")
00509                                 << "Both external Les Houches event and "
00510                                    "config file specify a PDF set.  "
00511                                    "User PDF will override external one."
00512                                 << std::endl;
00513 
00514                 pdfs.first = hwpram.MODPDF[0] != -111 ? hwpram.MODPDF[0] : -1;
00515                 pdfs.second = hwpram.MODPDF[1] != -111 ? hwpram.MODPDF[1] : -1;
00516         }
00517 
00518         hwpram.MODPDF[0] = pdfs.first;
00519         hwpram.MODPDF[1] = pdfs.second;
00520 
00521         if (externalPartons)
00522                 hwproc.IPROC = -1;
00523 
00524         // HERWIG preparations ...
00525         call(hwuinc);
00526         markStable(13);          // MU+
00527         markStable(-13);         // MU-
00528         markStable(3112);        // SIGMA+
00529         markStable(-3112);       // SIGMABAR+
00530         markStable(3222);        // SIGMA-
00531         markStable(-3222);       // SIGMABAR-
00532         markStable(3122);        // LAMBDA0
00533         markStable(-3122);       // LAMBDABAR0
00534         markStable(3312);        // XI-
00535         markStable(-3312);       // XIBAR+
00536         markStable(3322);        // XI0
00537         markStable(-3322);       // XI0BAR
00538         markStable(3334);        // OMEGA-
00539         markStable(-3334);       // OMEGABAR+
00540         markStable(211);         // PI+
00541         markStable(-211);        // PI-
00542         markStable(321);         // K+
00543         markStable(-321);        // K-
00544         markStable(310);         // K_S0
00545         markStable(130);         // K_L0
00546 
00547         // better: merge with declareStableParticles
00548         // and get the list from configuration / Geant4 / Core somewhere
00549 
00550         // initialize HERWIG event generation
00551         call(hweini);
00552 
00553         if (useJimmy)
00554                 call(jminit);
00555 
00556         edm::LogInfo(info.str());
00557 
00558         return true;
00559 }
00560 
00561 bool Herwig6Hadronizer::declareStableParticles(const std::vector<int> &pdgIds)
00562 {
00563         markStable(13);          // MU+
00564         markStable(-13);         // MU-
00565         markStable(3112);        // SIGMA+
00566         markStable(-3112);       // SIGMABAR+
00567         markStable(3222);        // SIGMA-
00568         markStable(-3222);       // SIGMABAR-
00569         markStable(3122);        // LAMBDA0
00570         markStable(-3122);       // LAMBDABAR0
00571         markStable(3312);        // XI-
00572         markStable(-3312);       // XIBAR+
00573         markStable(3322);        // XI0
00574         markStable(-3322);       // XI0BAR
00575         markStable(3334);        // OMEGA-
00576         markStable(-3334);       // OMEGABAR+
00577         markStable(211);         // PI+
00578         markStable(-211);        // PI-
00579         markStable(321);         // K+
00580         markStable(-321);        // K-
00581         markStable(310);         // K_S0
00582         markStable(130);         // K_L0
00583 
00584         for(std::vector<int>::const_iterator iter = pdgIds.begin();
00585             iter != pdgIds.end(); ++iter)
00586                 if (!markStable(*iter))
00587                         return false;
00588         return true;
00589 }
00590 
00591 bool Herwig6Hadronizer::declareSpecialSettings( const std::vector<std::string> )
00592 {
00593    return true;
00594 }
00595 
00596 void Herwig6Hadronizer::statistics()
00597 {
00598         if (!runInfo().internalXSec()) {
00599           // not set via LHE, so get it from HERWIG
00600           // the reason is that HERWIG doesn't compute the xsec
00601           // in all LHE modes
00602 
00603           double RNWGT = 1. / hwevnt.NWGTS;
00604           double AVWGT = hwevnt.WGTSUM * RNWGT;
00605 
00606           double xsec = 1.0e3 * AVWGT;
00607 
00608           runInfo().setInternalXSec(xsec);
00609         }
00610 }
00611 
00612 bool Herwig6Hadronizer::hadronize()
00613 {
00614         // hard process generation, parton shower, hadron formation
00615 
00616         InstanceWrapper wrapper(this);  // safe guard
00617 
00618         event().reset();
00619 
00620         // call herwig routines to create HEPEVT
00621 
00622         hwuine();       // initialize event
00623         
00624         if (callWithTimeout(10, hwepro)) { // process event and PS
00625           // We hung for more than 10 seconds
00626           int error = 199;
00627           hwwarn_("HWHGUP", &error);
00628         }
00629         
00630         hwbgen();       // parton cascades
00631 
00632         // call jimmy ... only if event is not killed yet by HERWIG
00633         if (useJimmy && doMPInteraction && !hwevnt.IERROR && call_hwmsct()) {
00634           if (lheEvent()) lheEvent()->count(lhef::LHERunInfo::kKilled);
00635           return false;
00636         }
00637         
00638         hwdhob();       // heavy quark decays
00639         hwcfor();       // cluster formation
00640         hwcdec();       // cluster decays
00641         
00642         // if event *not* killed by HERWIG, return true
00643         if (hwevnt.IERROR) {
00644           hwufne();     // finalize event, to keep system clean
00645           if (lheEvent()) lheEvent()->count(lhef::LHERunInfo::kKilled);
00646           return false;
00647         }
00648 
00649         if (lheEvent()) lheEvent()->count(lhef::LHERunInfo::kAccepted);
00650         return true;
00651 }
00652 
00653 void Herwig6Hadronizer::finalizeEvent()
00654 {
00655   lhef::LHEEvent::fixHepMCEventTimeOrdering(event().get());
00656   
00657   HepMC::PdfInfo pdfInfo;
00658   if(externalPartons) {
00659     lheEvent()->fillEventInfo( event().get() );
00660     lheEvent()->fillPdfInfo( &pdfInfo );
00661 
00662     // for MC@NLO: IDWRUP is not filled...
00663     if(event()->signal_process_id()==0)
00664       event()->set_signal_process_id( abs(hwproc.IPROC) );
00665 
00666   }
00667     
00668   HepMC::GenParticle* incomingParton = NULL;
00669   HepMC::GenParticle* targetParton = NULL;
00670   
00671   HepMC::GenParticle* incomingProton = NULL;
00672   HepMC::GenParticle* targetProton = NULL;
00673   
00674   // find incoming parton (first entry with IST=121)
00675   for(HepMC::GenEvent::particle_const_iterator it = event()->particles_begin(); 
00676       (it != event()->particles_end() && incomingParton==NULL); it++)
00677     if((*it)->status()==121) incomingParton = (*it);
00678   
00679   // find target parton (first entry with IST=122)
00680   for(HepMC::GenEvent::particle_const_iterator it = event()->particles_begin(); 
00681       (it != event()->particles_end() && targetParton==NULL); it++)
00682     if((*it)->status()==122) targetParton = (*it);
00683   
00684   // find incoming Proton (first entry ID=2212, IST=101)
00685   for(HepMC::GenEvent::particle_const_iterator it = event()->particles_begin(); 
00686       (it != event()->particles_end() && incomingProton==NULL); it++)
00687     if((*it)->status()==101 && (*it)->pdg_id()==2212) incomingProton = (*it);
00688   
00689   // find target Proton (first entry ID=2212, IST=102)
00690   for(HepMC::GenEvent::particle_const_iterator it = event()->particles_begin(); 
00691       (it != event()->particles_end() && targetProton==NULL); it++)
00692     if((*it)->status()==102 && (*it)->pdg_id()==2212) targetProton = (*it);
00693   
00694   // find hard scale Q (computed from colliding partons)
00695   if( incomingParton && targetParton ) {
00696     math::XYZTLorentzVector totMomentum(0,0,0,0);
00697     totMomentum+=incomingParton->momentum();
00698     totMomentum+=targetParton->momentum();
00699     double evScale = totMomentum.mass(); 
00700     double evScale2 = evScale*evScale; 
00701     
00702     // find alpha_QED & alpha_QCD         
00703     int one=1;
00704     double alphaQCD=hwualf_(&one,&evScale);
00705     double alphaQED=hwuaem_(&evScale2);
00706     
00707     if(!externalPartons || event()->event_scale() < 0) event()->set_event_scale(evScale);
00708     if(!externalPartons || event()->alphaQCD() < 0)    event()->set_alphaQCD(alphaQCD);
00709     if(!externalPartons || event()->alphaQED() < 0)    event()->set_alphaQED(alphaQED);
00710     
00711     if(!externalPartons || pdfInfo.x1() < 0) {
00712       // get the PDF information
00713       pdfInfo.set_id1( incomingParton->pdg_id()==21 ? 0 : incomingParton->pdg_id());
00714       pdfInfo.set_id2( targetParton->pdg_id()==21 ? 0 : targetParton->pdg_id());
00715       if( incomingProton && targetProton ) {
00716         double x1 = incomingParton->momentum().pz()/incomingProton->momentum().pz();
00717         double x2 = targetParton->momentum().pz()/targetProton->momentum().pz();        
00718         pdfInfo.set_x1(x1);
00719         pdfInfo.set_x2(x2);             
00720       }
00721       // we do not fill pdf1 & pdf2, since they are not easily available (what are they needed for anyways???)
00722       pdfInfo.set_scalePDF(evScale); // the same as Q above... does this make sense?
00723     } 
00724     
00725     if(!externalPartons || event()->signal_process_id() < 0) event()->set_signal_process_id( abs(hwproc.IPROC) );
00726     event()->set_pdf_info( pdfInfo );
00727   }
00728   
00729   // add event weight & PDF information
00730   if (lheRunInfo() != 0 && std::abs(lheRunInfo()->getHEPRUP()->IDWTUP) == 4)
00731     // in LHE weighting mode 4 the weight is an xsec, so convert form HERWIG
00732     // to standard CMS unit "picobarn"
00733     event()->weights().push_back( 1.0e3 * hwevnt.EVWGT );
00734   else
00735     event()->weights().push_back( hwevnt.EVWGT );
00736 
00737     
00738   // find final parton (first entry with IST=123)
00739   HepMC::GenParticle* finalParton = NULL;
00740   for(HepMC::GenEvent::particle_const_iterator it = event()->particles_begin(); 
00741       (it != event()->particles_end() && finalParton==NULL); it++)
00742     if((*it)->status()==123) finalParton = (*it);
00743   
00744   
00745   // add GenEventInfo & binning Values
00746   eventInfo().reset(new GenEventInfoProduct(event().get()));    
00747   if(finalParton) {
00748     double thisPt=finalParton->momentum().perp();
00749     eventInfo()->setBinningValues(std::vector<double>(1, thisPt));
00750   }
00751   
00752   // emulate PY6 status codes, if switched on...
00753   if (emulatePythiaStatusCodes)
00754     pythiaStatusCodes();          
00755   
00756 }
00757 
00758 
00759 bool Herwig6Hadronizer::decay()
00760 {
00761         // hadron decays
00762 
00763         InstanceWrapper wrapper(this);  // safe guard
00764 
00765         hwdhad();       // unstable particle decays
00766         hwdhvy();       // heavy flavour decays
00767         hwmevt();       // soft underlying event
00768 
00769         hwufne();       // finalize event
00770 
00771         if (hwevnt.IERROR)
00772                 return false;
00773 
00774         event().reset(new HepMC::GenEvent);
00775         if (!conv.fill_next_event(event().get()))
00776                 throw cms::Exception("Herwig6Error")
00777                         << "HepMC Conversion problems in event." << std::endl;
00778 
00779         // do particle ID conversion Herwig->PDG, if requested
00780         if ( fConvertToPDG ) {
00781            for ( HepMC::GenEvent::particle_iterator part = event()->particles_begin(); part != event()->particles_end(); ++part) {
00782              if ((*part)->pdg_id() != HepPID::translateHerwigtoPDT((*part)->pdg_id()))
00783                (*part)->set_pdg_id(HepPID::translateHerwigtoPDT((*part)->pdg_id()));
00784            }
00785         }
00786 
00787         return true;
00788 }
00789 
00790 bool Herwig6Hadronizer::residualDecay()
00791 {
00792         return true;
00793 }
00794 
00795 void Herwig6Hadronizer::upInit()
00796 {
00797         lhef::CommonBlocks::fillHEPRUP(lheRunInfo()->getHEPRUP());
00798         heprup_.pdfgup[0] = heprup_.pdfgup[1] = -1;
00799         heprup_.pdfsup[0] = heprup_.pdfsup[1] = -1;
00800         // we set up the PDFs ourselves
00801         
00802         // pass HERWIG paramaters fomr header (if present)
00803         std::string mcnloHeader="herwig6header";
00804         std::vector<lhef::LHERunInfo::Header> headers=lheRunInfo()->getHeaders();
00805         for(std::vector<lhef::LHERunInfo::Header>::const_iterator hIter=headers.begin();hIter!=headers.end(); ++hIter) {
00806           if(hIter->tag()==mcnloHeader){
00807             readMCatNLOfile=true;
00808             for(lhef::LHERunInfo::Header::const_iterator lIter=hIter->begin(); lIter != hIter->end(); ++lIter) {
00809               if((lIter->c_str())[0]!='#' && (lIter->c_str())[0]!='\n') {   // it's not a comment) 
00810                 if (!give(*lIter))
00811                   throw edm::Exception(edm::errors::Configuration)
00812                     << "Herwig 6 did not accept the following: \""
00813                     << *lIter << "\"." << std::endl;
00814               }
00815             }
00816           }
00817         }
00818 }
00819 
00820 void Herwig6Hadronizer::upEvnt()
00821 {
00822         lhef::CommonBlocks::fillHEPEUP(lheEvent()->getHEPEUP());
00823 
00824         // if MCatNLO external file is read, read comment & pass IHPRO to HERWIG
00825         if(readMCatNLOfile) {
00826           for(std::vector<std::string>::const_iterator iter=lheEvent()->getComments().begin();
00827               iter!=lheEvent()->getComments().end(); ++iter) {
00828             std::string toParse(iter->substr(1));
00829             if (!give(toParse))
00830               throw edm::Exception(edm::errors::Configuration)
00831                     << "Herwig 6 did not accept the following: \""
00832                     << toParse << "\"." << std::endl;
00833           }
00834         }
00835         
00836 }
00837 
00838 int Herwig6Hadronizer::pythiaStatusCode(const HepMC::GenParticle *p) const
00839 {
00840         int status = p->status();
00841 
00842         // weird 9922212 particles...
00843         if (status == 3 && !p->end_vertex())
00844                 return 2;
00845 
00846         if (status >= 1 && status <= 3)
00847                 return status;
00848 
00849         if (!p->end_vertex())
00850                 return 1;
00851 
00852         // let's prevent particles having status 3, if the identical
00853         // particle downstream is a better status 3 candidate
00854         int currentId = p->pdg_id();
00855         int orig = status;
00856         if (status == 123 || status == 124 ||
00857             status == 155 || status == 156 || status == 160 ||
00858             (status >= 195 && status <= 197)) {
00859                 for(const HepMC::GenParticle *q = p;;) {
00860                         const HepMC::GenVertex *vtx = q->end_vertex();
00861                         if (!vtx)
00862                                 break;
00863 
00864                         HepMC::GenVertex::particles_out_const_iterator iter;
00865                         for(iter = vtx->particles_out_const_begin();
00866                             iter != vtx->particles_out_const_end(); ++iter)
00867                                 if ((*iter)->pdg_id() == currentId)
00868                                         break;
00869 
00870                         if (iter == vtx->particles_out_const_end())
00871                                 break;
00872 
00873                         q = *iter;
00874                         if (q->status() == 3 ||
00875                             ((status == 120 || status == 123 ||
00876                               status == 124) && orig > 124))
00877                                 return 4;
00878                 }
00879         }
00880 
00881         int nesting = 0;
00882         for(;;) {
00883                 if ((status >= 120 && status <= 122) || status == 3) {
00884                         // avoid flagging status 3 if there is a
00885                         // better status 3 candidate upstream
00886                         if (externalPartons)
00887                                 return ((orig >= 121 && orig <= 124) ||
00888                                         orig == 3) ? 3 : 4;
00889                         else
00890                                 return (nesting ||
00891                                         (status != 3 && orig <= 124)) ? 3 : 4;
00892                 }
00893 
00894                 // check whether we are leaving the hard process
00895                 // including heavy resonance decays
00896                 if (!(status == 4 || status == 123 || status == 124 ||
00897                       status == 155 || status == 156 || status == 160 ||
00898                       (status >= 195 && status <= 197)))
00899                         break;
00900 
00901                 const HepMC::GenVertex *vtx = p->production_vertex();
00902                 if (!vtx || !vtx->particles_in_size())
00903                         break;
00904 
00905                 p = *vtx->particles_in_const_begin();
00906                 status = p->status();
00907 
00908                 int newId = p->pdg_id();
00909 
00910                 if (!newId)
00911                         break;
00912 
00913                 // nesting increases if we move to the next-best mother
00914                 if (newId != currentId) {
00915                         if (++nesting > 1 && externalPartons)
00916                                 break;
00917                         currentId = newId;
00918                 }
00919         }
00920 
00921         return 2; 
00922 }
00923 
00924 void Herwig6Hadronizer::pythiaStatusCodes()
00925 {
00926         for(HepMC::GenEvent::particle_iterator iter =
00927                                                 event()->particles_begin();
00928             iter != event()->particles_end(); iter++)
00929                 (*iter)->set_status(pythiaStatusCode(*iter));
00930 
00931         for(HepMC::GenEvent::particle_iterator iter =
00932                                                 event()->particles_begin();
00933             iter != event()->particles_end(); iter++)
00934                 if ((*iter)->status() == 4)
00935                         (*iter)->set_status(2);
00936 }
00937 
00938 #include "GeneratorInterface/ExternalDecays/interface/ExternalDecayDriver.h"
00939 
00940 typedef edm::GeneratorFilter<Herwig6Hadronizer, gen::ExternalDecayDriver> Herwig6GeneratorFilter;
00941 DEFINE_FWK_MODULE(Herwig6GeneratorFilter);
00942 
00943 typedef edm::HadronizerFilter<Herwig6Hadronizer, gen::ExternalDecayDriver> Herwig6HadronizerFilter;
00944 DEFINE_FWK_MODULE(Herwig6HadronizerFilter);