CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/src/PhysicsTools/HepMCCandAlgos/plugins/FlavorHistoryProducer.cc

Go to the documentation of this file.
00001 // This file was removed but it should not have been.
00002 // This comment is to restore it. 
00003 
00004 #include "PhysicsTools/HepMCCandAlgos/interface/FlavorHistoryProducer.h"
00005 
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "DataFormats/Math/interface/deltaR.h"
00008 
00009 // #include "DataFormats/Common/interface/ValueMap.h"
00010 // #include <iterators>
00011 
00012 
00013 // -------------------------------------------------------------
00014 // Identify the ancestry of the Quark
00015 // 
00016 // 
00017 // Matrix Element:
00018 //    Status 3 parent with precisely 2 "grandparents" that
00019 //    is outside of the "initial" section (0-5) that has the
00020 //    same ID as the status 2 parton in question. 
00021 //
00022 // Flavor excitation:
00023 //    If we find only one outgoing parton.
00024 //
00025 // Gluon splitting:
00026 //    Parent is a quark of a different flavor than the parton
00027 //    in question, or a gluon. 
00028 //    Can come from either ISR or FSR.
00029 //
00030 // True decay:
00031 //    Decays from a resonance like top, Higgs, etc.
00032 // -------------------------------------------------------------
00033 
00034 using namespace std;
00035 using namespace reco;
00036 using namespace edm;
00037 
00038 FlavorHistoryProducer::FlavorHistoryProducer( const ParameterSet & p ) :
00039   src_( p.getParameter<InputTag>( "src" ) ),
00040   matchedSrc_( p.getParameter<InputTag>( "matchedSrc") ),
00041   matchDR_ ( p.getParameter<double> ("matchDR") ),
00042   pdgIdToSelect_( p.getParameter<int> ("pdgIdToSelect") ),
00043   ptMinParticle_( p.getParameter<double>( "ptMinParticle") ),  
00044   ptMinShower_( p.getParameter<double>( "ptMinShower") ),  
00045   etaMaxParticle_( p.getParameter<double>( "etaMaxParticle" )),  
00046   etaMaxShower_( p.getParameter<double>( "etaMaxShower" )),
00047   flavorHistoryName_( p.getParameter<string>("flavorHistoryName") ),
00048   verbose_( p.getUntrackedParameter<bool>( "verbose" ) )
00049 {
00050   produces<FlavorHistoryEvent >(flavorHistoryName_);
00051 }
00052 
00053 FlavorHistoryProducer::~FlavorHistoryProducer() { 
00054 }
00055 
00056 void FlavorHistoryProducer::produce( Event& evt, const EventSetup& ) 
00057 {
00058   if ( verbose_ ) cout << "---------- Hello from FlavorHistoryProducer! -----" << endl;
00059   
00060   // Get a handle to the particle collection (OwnVector)
00061   Handle<CandidateView > particlesViewH;
00062   evt.getByLabel( src_, particlesViewH );
00063 
00064   Handle<CandidateView> matchedView;
00065   evt.getByLabel( matchedSrc_, matchedView );
00066 
00067   // Copy the View to an vector for easier iterator manipulation convenience
00068   vector<const Candidate* > particles;
00069   for( CandidateView::const_iterator p = particlesViewH->begin();  p != particlesViewH->end(); ++p ) {
00070     particles.push_back(&*p);
00071   }
00072 
00073   // List of indices for the partons to add
00074   vector<int> partonIndices;
00075   // List of progenitors for those partons
00076   vector<int> progenitorIndices;
00077   // List of sisters for those partons
00078   vector<int> sisterIndices;
00079   // Flavor sources
00080   vector<FlavorHistory::FLAVOR_T> flavorSources;
00081   
00082   // Make a new flavor history vector
00083   auto_ptr<FlavorHistoryEvent > flavorHistoryEvent ( new FlavorHistoryEvent () ) ;
00084 
00085   // ------------------------------------------------------------
00086   // Loop over partons
00087   // ------------------------------------------------------------
00088   vector<const Candidate* >::size_type j;
00089   vector<const Candidate* >::size_type j_max = particles.size();
00090   for( j=0; j<j_max; ++j ) {
00091 
00092     // Get the candidate
00093     const Candidate *p = particles[j];
00094     // Set up indices that we'll need for the flavor history
00095     vector<Candidate const *>::size_type partonIndex=j;
00096     vector<Candidate const *>::size_type progenitorIndex=j_max;
00097     bool foundProgenitor = false; 
00098     FlavorHistory::FLAVOR_T flavorSource=FlavorHistory::FLAVOR_NULL;
00099 
00100 
00101     int idabs = std::abs( (p)->pdgId() );
00102     int nDa = (p)->numberOfDaughters();
00103 
00104     // Check if we have a status 2 or 3 particle, which is a parton before the string.
00105     // Only consider quarks. 
00106     if ( idabs <= FlavorHistory::tQuarkId && p->status() == 2 &&
00107          idabs == pdgIdToSelect_ ) {
00108       // Ensure the parton in question has daughters 
00109       if ( nDa > 0 ) {
00110         // Ensure the parton passes some minimum kinematic cuts
00111         if((p)->pt() > ptMinShower_ && fabs((p)->eta())<etaMaxShower_) {
00112 
00113           if(verbose_) cout << "--------------------------" << endl;
00114           if(verbose_) cout << "Processing particle " << j << ", status = " << p->status() << ", pdg id = " << p->pdgId() << endl;
00115 
00116 
00117           //Main (but simple) workhorse to get all ancestors
00118           vector<Candidate const *> allParents;
00119           getAncestors( *p, allParents );
00120             
00121           if(verbose_) {
00122             cout << "Parents : " << endl;
00123             vector<Candidate const *>::const_iterator iprint = allParents.begin(),
00124               iprintend = allParents.end();
00125             for ( ; iprint != iprintend; ++iprint ) 
00126               cout << " status = " << (*iprint)->status() << ", pdg id = " << (*iprint)->pdgId() << ", pt = " << (*iprint)->pt() << endl;
00127           }
00128           
00129           // -------------------------------------------------------------
00130           // Identify the ancestry of the Quark
00131           // 
00132           // 
00133           // Matrix Element:
00134           //    Status 3 parent with precisely 2 "grandparents" that
00135           //    is outside of the "initial" section (0-5) that has the
00136           //    same ID as the status 2 parton in question. 
00137           //
00138           // Flavor excitation:
00139           //    If we find only one outgoing parton.
00140           //
00141           // Gluon splitting:
00142           //    Parent is a quark of a different flavor than the parton
00143           //    in question, or a gluon. 
00144           //    Can come from either ISR or FSR.
00145           //
00146           // True decay:
00147           //    Decays from a resonance like top, Higgs, etc.
00148           // -------------------------------------------------------------
00149           vector<Candidate const *>::size_type a_size = allParents.size();
00150 
00151           // 
00152           // Loop over all the ancestors of this parton and find the progenitor.
00153           // 
00154           for( vector<Candidate const *>::size_type i=0 ; i < a_size && !foundProgenitor; ++i ) {
00155             const Candidate * aParent=allParents[i];
00156             vector<Candidate const *>::const_iterator found = find(particles.begin(),particles.end(),aParent);
00157 
00158 
00159             // Get the index of the progenitor candidate
00160             progenitorIndex = found - particles.begin();
00161 
00162             int aParentId = std::abs(aParent->pdgId());
00163             
00164             // -----------------------------------------------------------------------
00165             // Here we examine particles that were produced after the collision
00166             // -----------------------------------------------------------------------
00167             if( progenitorIndex > 5 ) {
00168               // Here is where we have a matrix element process.
00169               // The signature is to have a status 3 parent with precisely 2 parents
00170               // that is outside of the "initial" section (0-5) that has the
00171               // same ID as the status 2 parton in question.
00172               // NOTE: If this parton has no sister, then this will be classified as
00173               // a flavor excitation. Often the only difference is that the matrix element 
00174               // cases have a sister, while the flavor excitation cases do not. 
00175               // If we do not find a sister below, this will be classified as a flavor
00176               // excitation. 
00177               if(  aParent->numberOfMothers() == 2 &&  
00178                   aParent->pdgId() == p->pdgId() && aParent->status() == 3 ) {
00179                 if(verbose_) cout << "Matrix Element progenitor" << endl;
00180                 if ( flavorSource == FlavorHistory::FLAVOR_NULL ) flavorSource = FlavorHistory::FLAVOR_ME;
00181                 foundProgenitor = true;
00182               } 
00183               // Here we have a true decay. Parent is not a quark or a gluon.
00184               else if( (aParentId>pdgIdToSelect_ && aParentId<FlavorHistory::gluonId) || 
00185                        aParentId > FlavorHistory::gluonId ) {
00186                 if(verbose_) cout << "Flavor decay progenitor" << endl;
00187                 if ( flavorSource == FlavorHistory::FLAVOR_NULL ) flavorSource = FlavorHistory::FLAVOR_DECAY;
00188                 foundProgenitor = true;
00189               }
00190             }// end if progenitorIndex > 5
00191           }// end loop over parents
00192 
00193           // Otherwise, classify it as gluon splitting. Take the first status 3 parton with 1 parent
00194           // that you see as the progenitor
00195           if ( !foundProgenitor  ) {
00196             if ( flavorSource == FlavorHistory::FLAVOR_NULL ) flavorSource = FlavorHistory::FLAVOR_GS;
00197             // Now get the parton with only one parent (the proton) and that is the progenitor
00198             for( vector<Candidate const *>::size_type i=0 ; i < a_size && !foundProgenitor; ++i ) {
00199               const Candidate * aParent=allParents[i];
00200               vector<Candidate const *>::const_iterator found = find(particles.begin(),particles.end(),aParent);
00201               // Get the index of the progenitor candidate
00202               progenitorIndex = found - particles.begin();
00203               
00204               if ( aParent->numberOfMothers() == 1 && aParent->status() == 3 ) {
00205                 foundProgenitor = true;
00206               }
00207             }// end loop over parents
00208           }// end if we haven't found a progenitor, and if we haven't found a status 3 parton of the same flavor
00209            // (i.e. end if examining gluon splitting)
00210         }// End if this parton passes some minimal kinematic cuts
00211       }// End if this particle is status 2 (has strings as daughters)
00212 
00213 
00214 
00215       // Make sure we've actually found a progenitor
00216       if ( !foundProgenitor ) progenitorIndex = j_max;
00217 
00218       // We've found the particle, add to the list
00219 
00220       partonIndices.push_back( partonIndex );
00221       progenitorIndices.push_back( progenitorIndex );
00222       flavorSources.push_back(flavorSource);
00223       sisterIndices.push_back( -1 ); // set below
00224         
00225     }// End if this particle was a status==2 parton
00226   }// end loop over particles
00227 
00228   // Now add sisters.
00229   // Also if the event is preliminarily classified as "matrix element", check to
00230   // make sure that they have a sister. If not, it is flavor excitation. 
00231   
00232   if ( verbose_ ) cout << "Making sisters" << endl;
00233   // First make sure nothing went terribly wrong:
00234   if ( partonIndices.size() == progenitorIndices.size() && partonIndices.size() > 0 ) {
00235     // Now loop over the candidates
00236     for ( unsigned int ii = 0; ii < partonIndices.size(); ++ii ) {
00237       // Get the iith particle
00238       const Candidate * candi = particles[partonIndices[ii]];
00239       if ( verbose_ ) cout << "   Sister candidate particle 1:  " << ii << ", pdgid = " << candi->pdgId() << ", status = " << candi->status() << endl;
00240       // Get the iith progenitor
00241       // Now loop over the other flavor history candidates and
00242       // attempt to find a sister to this one
00243       for ( unsigned int jj = 0; jj < partonIndices.size(); ++jj ) {
00244         if ( ii != jj ) {
00245           const Candidate * candj = particles[partonIndices[jj]];
00246       if ( verbose_ ) cout << "   Sister candidate particle 2:  " << jj << ", pdgid = " << candj->pdgId() << ", status = " << candj->status() << endl;
00247           // They should be opposite in pdgid and have the same status, and
00248           // the same progenitory.
00249           if ( candi->pdgId() == -1 * candj->pdgId() && candi->status() == candj->status()  ) {
00250             sisterIndices[ii] = partonIndices[jj];
00251             if ( verbose_ ) cout << "Parton " << partonIndices[ii] << " has sister " << sisterIndices[ii] << endl;
00252           }
00253         }
00254       }
00255 
00256       // Here, ensure that there is a sister. Otherwise this is "flavor excitation"
00257       if ( sisterIndices[ii] < 0 ) {
00258         if ( verbose_ ) cout << "No sister. Classified as flavor excitation" << endl;
00259         flavorSources[ii] = FlavorHistory::FLAVOR_EXC;
00260       } 
00261 
00262       if ( verbose_ ) cout << "Getting matched jet" << endl;
00263       // Get the closest match in the matched object collection
00264       CandidateView::const_iterator matched = getClosestJet( matchedView, *candi );
00265       CandidateView::const_iterator matchedBegin = matchedView->begin();
00266       CandidateView::const_iterator matchedEnd = matchedView->end();
00267 
00268       
00269       if ( verbose_ ) cout << "Getting sister jet" << endl;
00270       // Get the closest sister in the matched object collection, if sister is found
00271       CandidateView::const_iterator sister = 
00272         ( sisterIndices[ii] >= 0 && static_cast<unsigned int>(sisterIndices[ii]) < particles.size() ) ? 
00273         getClosestJet( matchedView, *particles[sisterIndices[ii]] ) :
00274         matchedEnd ;
00275 
00276       if ( verbose_ ) cout << "Making matched shallow clones : ";
00277       ShallowClonePtrCandidate matchedCand ;
00278       if ( matched != matchedEnd ) {
00279         if ( verbose_ ) cout << " found" << endl;
00280         matchedCand = ShallowClonePtrCandidate( CandidatePtr(matchedView, matched - matchedBegin ) );
00281       } else {
00282         if ( verbose_ ) cout << " NOT found" << endl;
00283       }
00284       
00285       if ( verbose_ ) cout << "Making sister shallow clones : ";
00286       ShallowClonePtrCandidate sisterCand;
00287       if ( sister != matchedEnd ) {
00288         if ( verbose_ ) cout << " found" << endl;
00289         sisterCand = ShallowClonePtrCandidate( CandidatePtr(matchedView, sister - matchedBegin ) );
00290       } else {
00291         if ( verbose_ ) cout << " NOT found" << endl;
00292       }
00293       
00294       if ( verbose_ ) cout << "Making history object" << endl;
00295       // Now create the flavor history object
00296       FlavorHistory history (flavorSources[ii], 
00297                              particlesViewH, 
00298                              partonIndices[ii], progenitorIndices[ii], sisterIndices[ii],
00299                              matchedCand,
00300                              sisterCand );
00301       if ( verbose_ ) cout << "Adding flavor history : " << history << endl;
00302       flavorHistoryEvent->push_back( history ); 
00303     }
00304   }
00305   
00306   // If we got any partons, cache them and then write them out
00307   if ( flavorHistoryEvent->size() > 0 ) {
00308 
00309     // Calculate some nice variables for FlavorHistoryEvent
00310     if ( verbose_ ) cout << "Caching flavor history event" << endl;
00311     flavorHistoryEvent->cache();
00312 
00313     if ( verbose_ ) {
00314       cout << "Outputting pdg id = " << pdgIdToSelect_ << " with nelements = " << flavorHistoryEvent->size() << endl;
00315       vector<FlavorHistory>::const_iterator i = flavorHistoryEvent->begin(),
00316         iend = flavorHistoryEvent->end();
00317       for ( ; i !=iend; ++i ) {
00318         cout << *i << endl;
00319       }
00320     }
00321   }
00322 
00323   // Now add the flavor history to the event record
00324   evt.put( flavorHistoryEvent, flavorHistoryName_ );
00325 }
00326 
00327  
00328 // Helper function to get all ancestors of this candidate
00329 void FlavorHistoryProducer::getAncestors(const Candidate &c,
00330                                          vector<Candidate const *> & moms )
00331 {
00332 
00333   if( c.numberOfMothers() == 1 ) {
00334     const Candidate * dau = &c;
00335     const Candidate * mom = c.mother();
00336     while ( dau->numberOfMothers() != 0) {
00337       moms.push_back( dau );
00338       dau = mom ;
00339       mom = dau->mother();
00340     } 
00341   } 
00342 }
00343 
00344 
00345 CandidateView::const_iterator 
00346 FlavorHistoryProducer::getClosestJet( Handle<CandidateView> const & pJets,
00347                                       reco::Candidate const & parton ) const 
00348 {
00349   double dr = matchDR_;
00350   CandidateView::const_iterator j = pJets->begin(),
00351     jend = pJets->end();
00352   CandidateView::const_iterator bestJet = pJets->end();
00353   for ( ; j != jend; ++j ) {
00354     double dri = deltaR( parton.p4(), j->p4() );
00355     if ( dri < dr ) {
00356       dr = dri;
00357       bestJet = j;
00358     }
00359   }
00360   return bestJet;
00361 }
00362 
00363 #include "FWCore/Framework/interface/MakerMacros.h"
00364 
00365 DEFINE_FWK_MODULE( FlavorHistoryProducer );