CMS 3D CMS Logo

/data/git/CMSSW_5_3_11_patch5/src/GeneratorInterface/Pythia8Interface/src/JetMatchingHook.cc

Go to the documentation of this file.
00001 #include "GeneratorInterface/Pythia8Interface/interface/JetMatchingHook.h"
00002 #include "GeneratorInterface/PartonShowerVeto/interface/JetMatchingMadgraph.h"
00003 #include "FWCore/Utilities/interface/Exception.h"
00004 
00005 #include "HepMC/HEPEVT_Wrapper.h"
00006 
00007 extern "C" {
00008 // this is patchup for Py6 common block because 
00009 // several elements of the VINT array are used in the matching process
00010 
00011     extern struct {
00012         int mint[400];
00013         double vint[400];
00014     } pyint1_;
00015 
00016 }
00017 
00018 
00019 using namespace gen;
00020 using namespace Pythia8;
00021 
00022 
00023 JetMatchingHook::JetMatchingHook( const edm::ParameterSet& ps, Info* info )
00024    : UserHooks(), fRunBlock(0), fEventBlock(0), fEventNumber(0), fInfoPtr(info), fJetMatching(0)
00025 {
00026 
00027    assert( fInfoPtr );
00028    
00029    std::string scheme = ps.getParameter<std::string>("scheme");
00030 
00031    if ( scheme == "Madgraph" )
00032    {
00033       fJetMatching = new JetMatchingMadgraph(ps);
00034    }
00035    else if ( scheme == "MLM" || scheme == "Alpgen" )
00036    {
00037         throw cms::Exception("JetMatching")
00038         << "Port of " << scheme << "scheme \"" << "\""
00039         " for parton-shower matching is still in progress."
00040         << std::endl;
00041    }
00042    else
00043       throw cms::Exception("InvalidJetMatching")
00044       << "Unknown scheme \"" << scheme << "\""
00045       " specified for parton-shower matching."
00046       << std::endl;
00047  
00048 }
00049 
00050 JetMatchingHook::~JetMatchingHook()
00051 {
00052    if ( fJetMatching ) delete fJetMatching;
00053 }
00054 
00055 void JetMatchingHook::init ( lhef::LHERunInfo* runInfo )
00056 {
00057 
00058    setLHERunInfo( runInfo );
00059    if ( !fRunBlock )
00060    {
00061       throw cms::Exception("JetMatching")
00062       << "Invalid RunInfo" << std::endl;
00063    
00064    }
00065    fJetMatching->init( runInfo );
00066    return; 
00067 
00068 }
00069 
00070 void JetMatchingHook::beforeHadronization( lhef::LHEEvent* lhee )
00071 {
00072 
00073    setLHEEvent( lhee );   
00074    fJetMatching->beforeHadronisation( lhee );
00075       
00076    // here we'll have to adjust, if needed, for "massless" particles
00077    // from earlier Madgraph version(s)
00078    // also, we'll have to setup elements of the Py6 fortran array 
00079    // VINT(357), VINT(358), VINT(360) and VINT(390)
00080    // if ( fJetMatching->getMatchingScheme() == "Madgraph" )
00081    // {
00082    //    
00083    // }
00084    
00085    fJetMatching->beforeHadronisationExec();  
00086    
00087    return;   
00088 
00089 }
00090 
00091 bool JetMatchingHook::doVetoPartonLevel( const Event& event )
00092 {
00093                   
00094    // extract "hardest" event - the output will go into workEvent, 
00095    // which is a data mamber of base class UserHooks
00096    //
00097    subEvent(event,true);
00098 
00099    setHEPEVT( event ); // here we pass in "full" event, not workEvent !
00100 
00101    // std::cout << " NPartons= " << hepeup_.nup << std::endl;
00102    
00103    if ( !hepeup_.nup || fJetMatching->isMatchingDone() )
00104    {
00105       return true;
00106    }
00107    
00108    // Note from JY:
00109    // match(...)input agrs here are reserved for future development and are irrelevat at this point
00110    // just for future references, they're: 
00111    // const HepMC::GenEvent* partonLevel,
00112    // const HepMC::GenEvent *finalState,
00113    // bool showeredFinalState
00114    //
00115    bool jmtch = fJetMatching->match( 0, 0, true ); // true if veto-ed, false if accepted (not veto-ed)
00116    if ( jmtch )
00117    {
00118       return true;
00119    }
00120          
00121    // Do not veto events that got this far
00122    //
00123    return false;
00124 
00125 }
00126 
00127 void JetMatchingHook::setHEPEVT( const Event& event )
00128 {
00129            
00130    HepMC::HEPEVT_Wrapper::zero_everything();   
00131       
00132    // service container for further mother-daughters links
00133    //
00134    std::vector<int> Py8PartonIdx; // position of original (LHE) partons in Py8::Event
00135    Py8PartonIdx.clear(); 
00136    std::vector<int> HEPEVTPartonIdx; // position of LHE partons in HEPEVT (incl. ME-generated decays)
00137    HEPEVTPartonIdx.clear(); 
00138 
00139    // general counter
00140    //
00141    int index = 0;
00142 
00143    int Py8PartonCounter = 0;
00144    int HEPEVTPartonCounter = 0;
00145    
00146    // find the fisrt parton that comes from LHE (ME-generated)
00147    // skip the incoming particles/partons
00148    for ( int iprt=1; iprt<event.size(); iprt++ )
00149    {
00150       const Particle& part = event[iprt];
00151       if ( abs(part.status()) < 22 ) continue; // below 10 is "service"
00152                                                // 11-19 are beam particles; below 10 is "service"
00153                                                // 21 is incoming partons      
00154       Py8PartonCounter = iprt;
00155       break;
00156    }
00157 
00158    const lhef::HEPEUP& hepeup = *fEventBlock->getHEPEUP();
00159    // start the counter from 2, because we don't want the incoming particles/oartons !
00160    for ( int iprt=2; iprt<hepeup.NUP; iprt++ )
00161    {
00162       index++;
00163       HepMC::HEPEVT_Wrapper::set_id( index, hepeup.IDUP[iprt] );
00164       HepMC::HEPEVT_Wrapper::set_status( index, 2 );
00165       HepMC::HEPEVT_Wrapper::set_momentum( index, hepeup.PUP[iprt][0], hepeup.PUP[iprt][1], hepeup.PUP[iprt][2], hepeup.PUP[iprt][4] );
00166       HepMC::HEPEVT_Wrapper::set_mass( index, hepeup.PUP[iprt][4] );
00167       // --> FIXME HepMC::HEPEVT_Wrapper::set_position( index, part.xProd(), part.yProd(), part.zProd(), part.tProd() );
00168       HepMC::HEPEVT_Wrapper::set_parents( index, 0, 0 ); // NO, not anymore to the "system particle"
00169       HepMC::HEPEVT_Wrapper::set_children( index, 0, 0 ); 
00170       if (  hepeup.MOTHUP[iprt].first > 2 && hepeup.MOTHUP[iprt].second > 2 ) // decay from LHE, will NOT show at the start of Py8 event !!!
00171       {
00172          HEPEVTPartonCounter++;
00173          continue;
00174       }
00175       Py8PartonIdx.push_back( Py8PartonCounter );
00176       Py8PartonCounter++;
00177       HEPEVTPartonIdx.push_back( HEPEVTPartonCounter);
00178       HEPEVTPartonCounter++;   
00179    }
00180       
00181    HepMC::HEPEVT_Wrapper::set_number_entries( index );   
00182          
00183    // now that the initial partons are in, attach parton-level from Pythia8
00184    // do NOT reset index as we need to *add* more particles sequentially
00185    //
00186    for ( int iprt=1; iprt<workEvent.size(); iprt++ ) // from 0-entry (system) or from 1st entry ???
00187    {
00188    
00189       const Particle& part = workEvent[iprt];
00190       
00191 
00192       if ( part.status() != 62 ) continue;
00193                   
00194       index++;
00195       HepMC::HEPEVT_Wrapper::set_id( index, part.id() );
00196       
00197       // HepMC::HEPEVT_Wrapper::set_status( index, event.statusHepMC(iprt) ); 
00198       HepMC::HEPEVT_Wrapper::set_status( index, 1 );      
00199       HepMC::HEPEVT_Wrapper::set_momentum( index, part.px(), part.py(), part.pz(), part.e() );
00200       HepMC::HEPEVT_Wrapper::set_mass( index, part.m() );
00201       HepMC::HEPEVT_Wrapper::set_position( index, part.xProd(), part.yProd(), part.zProd(), part.tProd() );
00202       HepMC::HEPEVT_Wrapper::set_parents( index, 0, 0 ); // just set to 0 like in Py6...
00203                                                          // although for some, mother will need to be re-set properly !
00204       HepMC::HEPEVT_Wrapper::set_children( index, 0, 0 );
00205 
00206       // now refine mother-daughters links, where applicable
00207       
00208       int parentId = getAncestor( part.daughter1(), event );
00209       
00210       if ( parentId <= 0 ) continue;
00211 
00212       for ( int idx=0; idx<(int)Py8PartonIdx.size(); idx++ )
00213       {
00214          if ( parentId == Py8PartonIdx[idx] )
00215          {
00216             int idx1 = HEPEVTPartonIdx[idx]; 
00217             HepMC::HEPEVT_Wrapper::set_parents( index, idx1+1, idx1+1 ); 
00218             break;
00219          }
00220       }
00221 
00222    }  
00223      
00224    HepMC::HEPEVT_Wrapper::set_number_entries( index );
00225    
00226    HepMC::HEPEVT_Wrapper::set_event_number( fEventNumber ); // well, if you know it... well, it's one of the counters...
00227    
00228 //   HepMC::HEPEVT_Wrapper::print_hepevt();
00229    
00230    return;
00231 
00232 }
00233 
00234 int JetMatchingHook::getAncestor( int pos, const Event& fullEvent )
00235 {
00236 
00237    int parentId = fullEvent[pos].mother1();
00238    int parentPrevId = 0;
00239    int counter = pos;
00240    
00241    while ( parentId > 0 )
00242    {               
00243          if ( parentId == fullEvent[counter].mother2() ) // carbon copy, keep walking up
00244          {
00245             parentPrevId = parentId;
00246             counter = parentId;
00247             parentId = fullEvent[parentPrevId].mother1();
00248             continue;
00249          }
00250          
00251          // we get here if not a carbon copy
00252          
00253          // let's check if it's a normal process, etc.
00254          //
00255          if ( (parentId < parentPrevId) || parentId < fullEvent[counter].mother2() ) // normal process
00256          {
00257             
00258             // first of all, check if hard block
00259             if ( abs(fullEvent[counter].status()) == 22 || abs(fullEvent[counter].status()) == 23 )
00260             {
00261                // yes, it's the hard block
00262                // we got what we want, and can exit now !
00263                parentId = counter;
00264                break;
00265             }
00266             else
00267             {
00268                parentPrevId = parentId;
00269                parentId = fullEvent[parentPrevId].mother1();
00270             }
00271          }
00272          else if ( parentId > parentPrevId || parentId > pos ) // "circular"/"forward-pointing parent" - intermediate process
00273          {
00274             parentId = -1;
00275             break;
00276          }
00277 
00278          // additional checks... although we shouldn't be geeting here all that much...
00279          //      
00280          if ( abs(fullEvent[parentId].status()) == 22 || abs(fullEvent[parentId].status())== 23 ) // hard block
00281          {
00282             break;
00283          }       
00284          if ( abs(fullEvent[parentId].status()) < 22 ) // incoming
00285          {
00286             parentId = -1;
00287             break;
00288          } 
00289    }
00290    
00291    return parentId;
00292 
00293 }