CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/GeneratorInterface/Pythia8Interface/plugins/Py8toJetInput.cc

Go to the documentation of this file.
00001 #include "GeneratorInterface/Pythia8Interface/plugins/Py8toJetInput.h"
00002 
00003 #include "SimDataFormats/GeneratorProducts/interface/LHECommonBlocks.h"
00004 #include "GeneratorInterface/LHEInterface/interface/LHERunInfo.h"
00005 #include "GeneratorInterface/LHEInterface/interface/LHEEvent.h"
00006 
00007 const std::vector<fastjet::PseudoJet> 
00008 Py8toJetInput::fillJetAlgoInput( const Event& event, const Event& workEvent,
00009                                  const lhef::LHEEvent* lhee,
00010                                  const std::vector<int>* typeIdx )
00011 {
00012 
00013    fJetInput.clear();
00014    
00015    Event workEventJet = workEvent;
00016    
00017    const lhef::HEPEUP& hepeup = *lhee->getHEPEUP();
00018          
00019    std::set< int > typeSet[3];
00020    
00021    // FIXME !!!
00022    // This is not safe to assume it's 3 because we're passing in a pointer
00023    // and we do NOT know what the actuial size is. I'll have to improve it.
00024    //
00025    for ( size_t i=0; i<3; i++ )
00026    {
00027       typeSet[i].clear();
00028       for ( size_t j=0; j<typeIdx[i].size(); j++ )
00029       {
00030 
00031          // HEPEUP and Py8 event record are shifted by 3 
00032          // (system particle + 2 beam particles in Py8 event)
00033          // ... EXCEPT FOR THE DECAY PRODUCTS IF DONE AT THE ME LEVEL !!!!!
00034          // ... in such case, the decay productes get gutted out of the sequence 
00035          // and get placed in Py8 Event later on...
00036          // so we need to figure out the shift
00037          int pos = typeIdx[i][j]; 
00038          int shift = 3;
00039          // skip the first 2 entrirs in HEPEUP - they're incoming partons
00040          for ( int ip=2; ip<pos; ip++ )
00041          {
00042             // alternative can be: moth1 != 1 && moth2 !=2...
00043             // but moth1 == moth2 means pointer to the same mother t
00044             // that can only be a resonance, unless moth1==moth2==0
00045             //
00046             if ( hepeup.MOTHUP[ip].first == hepeup.MOTHUP[ip].second )
00047             {
00048                shift--;
00049             }    
00050          }       
00051          pos += shift;
00052          // typeSet[i].insert( event[pos].daughter1() );
00053          typeSet[i].insert( pos );
00054       }
00055    }   
00056   
00057   // int iTypeEnd = (typeIdx[1].empty()) ? 1 : 2;
00058 
00059 // --> FIXME !!!
00060    int iType = 0; // only LIGHT jets for now
00061    int jetAllow = 0; // hardcoded for now for the same value as is set in Steve's example
00062    // at present, not even in use...
00063    // int jetMatch = 0; // hardcoded for now for the same value as is set in Steve's example
00064    
00065   // Loop over particles and decide what to pass to the jet algorithm
00066   for (int i = 0; i < workEventJet.size(); ++i) 
00067   {
00068 
00069     if (!workEventJet[i].isFinal()) continue;
00070 
00071     // jetAllow option to disallow certain particle types
00072     if (jetAllow == 1) 
00073     {
00074 
00075       // Original AG+Py6 algorithm explicitly excludes tops,
00076       // leptons and photons.
00077       int id = workEventJet[i].idAbs();
00078       if ((id >= 11 && id <= 16) || id == ID_TOP || id == ID_PHOTON) 
00079       {
00080         workEventJet[i].statusNeg();
00081         continue;
00082       }
00083     }
00084 
00085     // Get the index of this particle in original event
00086     int idx = workEventJet[i].daughter1();
00087 
00088     // Start with particle idx, and afterwards track mothers
00089     while (true) 
00090     {
00091 
00092       // Light jets
00093       if (iType == 0) 
00094       {
00095 
00096         // Do not include if originates from heavy jet or 'other'
00097         if (typeSet[1].find(idx) != typeSet[1].end() ||
00098             typeSet[2].find(idx) != typeSet[2].end()) 
00099         {
00100           workEventJet[i].statusNeg();
00101           break;
00102         }
00103 
00104         // Made it to start of event record so done
00105         if (idx == 0) 
00106         {
00107            break;
00108         }
00109         // Otherwise next mother and continue
00110         idx = event[idx].mother1();
00111 
00112       // Heavy jets
00113       } 
00114       else if (iType == 1) 
00115       {
00116 
00117         // Only include if originates from heavy jet
00118         if (typeSet[1].find(idx) != typeSet[1].end()) break;
00119 
00120         // Made it to start of event record with no heavy jet mother,
00121         // so DO NOT include particle
00122         if (idx == 0) 
00123         {
00124           workEventJet[i].statusNeg();
00125           break;
00126         }
00127 
00128         // Otherwise next mother and continue
00129         idx = event[idx].mother1();
00130 
00131       } // if (iType)
00132     } // while (true)
00133   } // for (i)
00134 
00135   // For jetMatch = 2, insert ghost particles corresponding to
00136   // each hard parton in the original process
00137 /*
00138   if (jetMatch > 0) 
00139   {
00140 
00141     for (int i = 0; i < int(typeIdx[iType].size()); i++) 
00142     {
00143       // Get y/phi of the parton
00144       Vec4   pIn = eventProcess[typeIdx[iType][i]].p();
00145       double y   = Vec4y(pIn);
00146       double phi = pIn.phi();
00147 
00148       // Create a ghost particle and add to the workEventJet
00149       double e   = MG5_GHOSTENERGY;
00150       double e2y = exp(2. * y);
00151       double pz  = e * (e2y - 1.) / (e2y + 1.);
00152       double pt  = sqrt(e*e - pz*pz);
00153       double px  = pt * cos(phi);
00154       double py  = pt * sin(phi);
00155       workEventJet.append(Particle(ID_GLUON, 99, 0, 0, 0, 0, 0, 0,
00156                                 px, py, pz, e, 0., 0, 9.));
00157 
00158     } // for (i)
00159   } // if (jetMatch == 2)
00160 */
00161 
00162    for ( int i=0; i<workEventJet.size(); i++ )
00163    {
00164        
00165        // fisrt, weed out all entries marked with statusNeg();
00166        //
00167        if ( workEventJet[i].status() < 0 ) continue;
00168        
00169        
00170        // now weed out all entries above etaMax 
00171        // in principle, we can use etaJetMaxAlgo because it's set equal to etaJetMax
00172        // as for etaJetMax, it gets set to memain_.etaclmax
00173        //
00174        if ( fabs(workEventJet[i].eta()) > fJetEtaMax ) continue ; 
00175        
00176        // need to double check if native FastJet understands Py8 Event format
00177        // in general, PseudoJet gets formed from (px,py,pz,E)
00178        //
00179        fastjet::PseudoJet partTmp = workEventJet[i];
00180        fJetInput.push_back( partTmp );       
00181    }
00182       
00183    return fJetInput;
00184 
00185 }
00186 
00187 
00188 int Py8toJetInput::getAncestor( int pos, const Event& fullEvent, const Event& workEvent )
00189 {
00190 
00191    int parentId = fullEvent[pos].mother1();
00192    int parentPrevId = 0;
00193    int counter = pos;
00194    
00195    while ( parentId > 0 )
00196    {               
00197          if ( parentId == fullEvent[counter].mother2() ) // carbon copy, keep walking up
00198          {
00199             parentPrevId = parentId;
00200             counter = parentId;
00201             parentId = fullEvent[parentPrevId].mother1();
00202             continue;
00203          }
00204          
00205          // we get here if not a carbon copy
00206          
00207          // let's check if it's a normal process, etc.
00208          //
00209          if ( (parentId < parentPrevId) || parentId < fullEvent[counter].mother2() ) // normal process
00210          {
00211             
00212             // first of all, check if hard block
00213             if ( abs(fullEvent[counter].status()) == 22 || abs(fullEvent[counter].status()) == 23 )
00214             {
00215                // yes, it's the hard block
00216                // we got what we want, and can exit now !
00217                parentId = counter;
00218                break;
00219             }
00220             else
00221             {
00222                parentPrevId = parentId;
00223                parentId = fullEvent[parentPrevId].mother1();
00224             }
00225          }
00226          else if ( parentId > parentPrevId || parentId > pos ) // "circular"/"forward-pointing parent" - intermediate process
00227          {
00228             parentId = -1;
00229             break;
00230          }
00231 
00232          // additional checks... although we shouldn't be geeting here all that much...
00233          //      
00234          if ( abs(fullEvent[parentId].status()) == 22 || abs(fullEvent[parentId].status())== 23 ) // hard block
00235          {
00236             break;
00237          }       
00238          if ( abs(fullEvent[parentId].status()) < 22 ) // incoming
00239          {
00240             parentId = -1;
00241             break;
00242          } 
00243    }
00244    
00245    return parentId;
00246 
00247 }
00248 
00249 #include "HepMC/HEPEVT_Wrapper.h"
00250 #include <cassert>
00251 
00252 const std::vector<fastjet::PseudoJet> 
00253 Py8toJetInputHEPEVT::fillJetAlgoInput( const Event& event, const Event& workEvent, 
00254                                        const lhef::LHEEvent* lhee,
00255                                        const std::vector<int>* )
00256 {
00257 
00258    fJetInput.clear();
00259 
00260    HepMC::HEPEVT_Wrapper::zero_everything();   
00261       
00262    // service container for further mother-daughters links
00263    //
00264    std::vector<int> Py8PartonIdx; // position of original (LHE) partons in Py8::Event
00265    Py8PartonIdx.clear(); 
00266    std::vector<int> HEPEVTPartonIdx; // position of LHE partons in HEPEVT (incl. ME-generated decays)
00267    HEPEVTPartonIdx.clear(); 
00268 
00269    // general counter
00270    //
00271    int index = 0;
00272 
00273    int Py8PartonCounter = 0;
00274    int HEPEVTPartonCounter = 0;
00275    
00276    // find the fisrt parton that comes from LHE (ME-generated)
00277    // skip the incoming particles/partons
00278    for ( int iprt=1; iprt<event.size(); iprt++ )
00279    {
00280       const Particle& part = event[iprt];
00281       if ( abs(part.status()) < 22 ) continue; // below 10 is "service"
00282                                                // 11-19 are beam particles; below 10 is "service"
00283                                                // 21 is incoming partons      
00284       Py8PartonCounter = iprt;
00285       break;
00286    }
00287 
00288    const lhef::HEPEUP& hepeup = *lhee->getHEPEUP();
00289    // start the counter from 2, because we don't want the incoming particles/oartons !
00290    for ( int iprt=2; iprt<hepeup.NUP; iprt++ )
00291    {
00292       index++;
00293       HepMC::HEPEVT_Wrapper::set_id( index, hepeup.IDUP[iprt] );
00294       HepMC::HEPEVT_Wrapper::set_status( index, 2 );
00295       HepMC::HEPEVT_Wrapper::set_momentum( index, hepeup.PUP[iprt][0], hepeup.PUP[iprt][1], hepeup.PUP[iprt][2], hepeup.PUP[iprt][4] );
00296       HepMC::HEPEVT_Wrapper::set_mass( index, hepeup.PUP[iprt][4] );
00297       // --> FIXME HepMC::HEPEVT_Wrapper::set_position( index, part.xProd(), part.yProd(), part.zProd(), part.tProd() );
00298       HepMC::HEPEVT_Wrapper::set_parents( index, 0, 0 ); // NO, not anymore to the "system particle"
00299       HepMC::HEPEVT_Wrapper::set_children( index, 0, 0 ); 
00300       if (  hepeup.MOTHUP[iprt].first > 2 && hepeup.MOTHUP[iprt].second > 2 ) // decay from LHE, will NOT show at the start of Py8 event !!!
00301       {
00302          HEPEVTPartonCounter++;
00303          continue;
00304       }
00305       Py8PartonIdx.push_back( Py8PartonCounter );
00306       Py8PartonCounter++;
00307       HEPEVTPartonIdx.push_back( HEPEVTPartonCounter);
00308       HEPEVTPartonCounter++;   
00309    }
00310       
00311    HepMC::HEPEVT_Wrapper::set_number_entries( index );   
00312          
00313    // now that the initial partons are in, attach parton-level from Pythia8
00314    // do NOT reset index as we need to *add* more particles sequentially
00315    //
00316    for ( int iprt=1; iprt<workEvent.size(); iprt++ ) // from 0-entry (system) or from 1st entry ???
00317    {
00318    
00319       const Particle& part = workEvent[iprt];
00320       
00321 
00322 //      if ( part.status() != 62 ) continue;
00323       if ( part.status() < 51 ) continue;
00324       index++;
00325       HepMC::HEPEVT_Wrapper::set_id( index, part.id() );
00326       
00327       // HepMC::HEPEVT_Wrapper::set_status( index, event.statusHepMC(iprt) ); 
00328       HepMC::HEPEVT_Wrapper::set_status( index, 1 );      
00329       HepMC::HEPEVT_Wrapper::set_momentum( index, part.px(), part.py(), part.pz(), part.e() );
00330       HepMC::HEPEVT_Wrapper::set_mass( index, part.m() );
00331       HepMC::HEPEVT_Wrapper::set_position( index, part.xProd(), part.yProd(), part.zProd(), part.tProd() );
00332       HepMC::HEPEVT_Wrapper::set_parents( index, 0, 0 ); // just set to 0 like in Py6...
00333                                                          // although for some, mother will need to be re-set properly !
00334       HepMC::HEPEVT_Wrapper::set_children( index, 0, 0 );
00335 
00336       // now refine mother-daughters links, where applicable
00337       
00338       int parentId = getAncestor( part.daughter1(), event, workEvent );
00339       
00340       if ( parentId <= 0 ) continue;
00341 
00342       for ( int idx=0; idx<(int)Py8PartonIdx.size(); idx++ )
00343       {
00344          if ( parentId == Py8PartonIdx[idx] )
00345          {
00346             int idx1 = HEPEVTPartonIdx[idx]; 
00347             HepMC::HEPEVT_Wrapper::set_parents( index, idx1+1, idx1+1 ); 
00348             break;
00349          }
00350       }
00351 
00352    } 
00353         
00354    HepMC::HEPEVT_Wrapper::set_number_entries( index );
00355 
00356 // --> FIXME   HepMC::HEPEVT_Wrapper::set_event_number( fEventNumber ); // well, if you know it... well, it's one of the counters...
00357       
00358 //   HepMC::HEPEVT_Wrapper::print_hepevt();
00359    
00360    return fJetInput;
00361 
00362 }