CMS 3D CMS Logo

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 
00008 // #include "DataFormats/Common/interface/ValueMap.h"
00009 // #include <iterators>
00010 
00011 
00012 // -------------------------------------------------------------
00013 // Identify the ancestry of the Quark
00014 // 
00015 // 
00016 // Matrix Element:
00017 //    Status 3 parent with precisely 2 "grandparents" that
00018 //    is outside of the "initial" section (0-5) that has the
00019 //    same ID as the status 2 parton in question. 
00020 //    NOTE: This is not the actual ultimate progenitor,
00021 //    but this is the signature of matrix element decays.
00022 //    The ultimate progenitor is the parent of the status 3
00023 //    parton.
00024 //
00025 // Flavor excitation:
00026 //    Almost the same as the matrix element classification,
00027 //    but has only one outgoing parton product instead of two.
00028 //
00029 // Gluon splitting:
00030 //    Parent is a quark of a different flavor than the parton
00031 //    in question, or a gluon. Can come from either ISR or FSR.
00032 //
00033 // True decay:
00034 //    Decays from a resonance like top, Higgs, etc.
00035 // -------------------------------------------------------------
00036 
00037 using namespace std;
00038 using namespace reco;
00039 using namespace edm;
00040 
00041 
00042 ostream & operator<<( ostream & out, Candidate const & cand) 
00043 {
00044   char buff[1000];
00045   sprintf(buff, "%5d, status = %5d, nmo = %5d, nda = %5d, pt = %6.2f, eta = %6.2f, phi = %6.2f, m = %6.2f", 
00046           cand.pdgId(), cand.status(), 
00047           cand.numberOfMothers(),
00048           cand.numberOfDaughters(),
00049           cand.pt(), cand.eta(), cand.phi(), cand.mass() );
00050   out << buff;
00051   return out;
00052 }
00053 
00054 ostream & operator<<( ostream & out, FlavorHistory const & cand) 
00055 {
00056   out << "Source     = " << cand.flavorSource() << endl;
00057   if ( cand.hasParton() ) 
00058     out << "Parton     = " << cand.parton().key() << " : " << *(cand.parton()) << endl;
00059   if ( cand.hasProgenitor() ) 
00060     out << "Progenitor = " << cand.progenitor().key() << " : " << *(cand.progenitor()) << endl;
00061   if ( cand.hasSister() ) 
00062     out << "Sister     = " << cand.sister().key() << " : " << *(cand.sister()) << endl;
00063   if ( cand.hasParton() ) {
00064     out << "Ancestry: " << endl;
00065     Candidate const * ipar = cand.parton()->mother();
00066     while ( ipar->numberOfMothers() > 0 ) {
00067       out << *ipar << endl;
00068       ipar = ipar->mother();
00069     }
00070   }
00071   return out;
00072 }
00073 
00074 FlavorHistoryProducer::FlavorHistoryProducer( const ParameterSet & p ) :
00075   src_( p.getParameter<InputTag>( "src" ) ),
00076   pdgIdToSelect_( p.getParameter<int> ("pdgIdToSelect") ),
00077   ptMinParticle_( p.getParameter<double>( "ptMinParticle") ),  
00078   ptMinShower_( p.getParameter<double>( "ptMinShower") ),  
00079   etaMaxParticle_( p.getParameter<double>( "etaMaxParticle" )),  
00080   etaMaxShower_( p.getParameter<double>( "etaMaxShower" )),
00081   flavorHistoryName_( p.getParameter<string>("flavorHistoryName") ),
00082   verbose_( p.getUntrackedParameter<bool>( "verbose" ) )
00083 {
00084   produces<vector<FlavorHistory> >(flavorHistoryName_);
00085 }
00086 
00087 FlavorHistoryProducer::~FlavorHistoryProducer() { 
00088 }
00089 
00090 void FlavorHistoryProducer::beginJob( const EventSetup & es ) {
00091 }
00092 
00093 void FlavorHistoryProducer::produce( Event& evt, const EventSetup& ) 
00094 {
00095 
00096   if ( verbose_ ) cout << "Producing flavor history" << endl;
00097   
00098   // Get a handle to the particle collection (OwnVector)
00099   Handle<CandidateView > particlesViewH;
00100   evt.getByLabel( src_, particlesViewH );
00101 
00102   // Copy the View to an vector for easier iterator manipulation convenience
00103   vector<const Candidate* > particles;
00104   for( CandidateView::const_iterator p = particlesViewH->begin();  p != particlesViewH->end(); ++p ) {
00105     particles.push_back(&*p);
00106   }
00107   
00108   // Make a new flavor history vector
00109   auto_ptr<vector<FlavorHistory> > flavorHistoryVector ( new vector<FlavorHistory> () ) ;
00110 
00111   // ------------------------------------------------------------
00112   // Loop over partons
00113   // ------------------------------------------------------------
00114   vector<const Candidate* >::size_type j;
00115   vector<const Candidate* >::size_type j_max = particles.size();
00116   for( j=0; j<j_max; ++j ) {
00117 
00118     if ( verbose_ ) cout << "Processing particle " << j << endl;
00119 
00120     // Get the candidate
00121     const Candidate *p = particles[j];
00122     // Set up indices that we'll need for the flavor history
00123     vector<Candidate const *>::size_type partonIndex=j;
00124     vector<Candidate const *>::size_type progenitorIndex=0;
00125     vector<Candidate const *>::size_type sisterIndex=0;
00126     bool foundProgenitor = false; 
00127     bool foundSister = false;
00128     FlavorHistory::FLAVOR_T flavorSource=FlavorHistory::FLAVOR_NULL;
00129 
00130 
00131     int idabs = abs( (p)->pdgId() );
00132     int nDa = (p)->numberOfDaughters();
00133 
00134     // Check if we have a status 2 or 3 particle, which is a parton before the string.
00135     // Only consider quarks. 
00136     if ( idabs <= FlavorHistory::tQuarkId && p->status() == 2 ) {
00137       // Ensure the parton in question has daughters 
00138       if ( nDa > 0 ) {
00139         // Ensure the parton passes some minimum kinematic cuts
00140         if((p)->pt() > ptMinShower_ && fabs((p)->eta())<etaMaxShower_) {
00141 
00142 
00143           if(verbose_) cout << "--------------------------" << endl;
00144           if(verbose_) cout << "Processing particle " << j  << " = " << *p << endl;
00145 
00146 
00147           //Main (but simple) workhorse to get all ancestors
00148           vector<Candidate const *> allParents;
00149           getAncestors( *p, allParents );
00150             
00151           if(verbose_) {
00152             cout << "Parents : " << endl;
00153             vector<Candidate const *>::const_iterator iprint = allParents.begin(),
00154               iprintend = allParents.end();
00155             for ( ; iprint != iprintend; ++iprint ) 
00156               cout << **iprint << endl;
00157           }
00158           
00159 
00160           // -------------------------------------------------------------
00161           // Identify the ancestry of the Quark
00162           // 
00163           // 
00164           // Matrix Element:
00165           //    Status 3 parent with precisely 2 "grandparents" that
00166           //    is outside of the "initial" section (0-5) that has the
00167           //    same ID as the status 2 parton in question. 
00168           //    NOTE: This is not the actual ultimate progenitor,
00169           //    but this is the signature of matrix element decays.
00170           //    The ultimate progenitor is the parent of the status 3
00171           //    parton.
00172           //
00173           // Flavor excitation:
00174           //    Almost the same as the matrix element classification,
00175           //    but has only one outgoing parton product instead of two.
00176           //
00177           // Gluon splitting:
00178           //    Parent is a quark of a different flavor than the parton
00179           //    in question, or a gluon. Can come from either ISR or FSR.
00180           //
00181           // True decay:
00182           //    Decays from a resonance like top, Higgs, etc.
00183           // -------------------------------------------------------------
00184           vector<Candidate const *>::size_type a_size = allParents.size();
00185           int parentIndex=0;
00186 
00187           // 
00188           // Loop over all the ancestors of this parton and find the progenitor.
00189           // 
00190           for( vector<Candidate const *>::size_type i=0 ; i < a_size && !foundProgenitor; ++i,++parentIndex ) {
00191             const Candidate * aParent=allParents[i];
00192             vector<Candidate const *>::const_iterator found = find(particles.begin(),particles.end(),aParent);
00193 
00194 
00195             // Get the index of the progenitor candidate
00196             progenitorIndex = found - particles.begin();
00197 
00198             int aParentId = abs(aParent->pdgId());
00199 
00200             // -----------------------------------------------------------------------
00201             // Here we examine particles that were produced after the collision
00202             // -----------------------------------------------------------------------
00203             if( aParent->numberOfMothers() == 2 && progenitorIndex > 5 ) {
00204               // Here is where we have a matrix element process.
00205               // The signature is to have a status 3 parent with precisely 2 parents
00206               // that is outside of the "initial" section (0-5) that has the
00207               // same ID as the status 2 parton in question.
00208               // NOTE: This is not the actual ultimate progenitor, but this is
00209               // the signature of matrix element decays. The ultimate progentitor
00210               // is the parent of the status 3 parton. 
00211               // ALSO NOTE: If this parton has no sister, then this will be classified as
00212               // a flavor excitation. The only difference, since the initial states are
00213               // mostly gluons, is that the matrix element cases have a sister,
00214               // while the flavor excitation cases do not. 
00215               // If we do not find a sister below, this will be classified as a flavor
00216               // excitation. 
00217               if( aParentId == pdgIdToSelect_ ) {
00218                 if(verbose_) cout << "Matrix Element progenitor" << endl;
00219                 flavorSource = FlavorHistory::FLAVOR_ME;
00220 
00221                 // The "true" progenitor is the next parent in the list (the parent of this
00222                 // progenitor).
00223                 if ( i != a_size - 1 ) {
00224                   const Candidate * progenitorCand = allParents[i+1];
00225                   vector<Candidate const *>::const_iterator foundAgain = find( particles.begin(),
00226                                                                                particles.end(),
00227                                                                                progenitorCand );
00228                   progenitorIndex = foundAgain - particles.begin();
00229                   foundProgenitor = true;
00230 
00231                 } else {
00232                   edm::LogWarning("UnexpectedFormat") << "Error! Parentage information in FlavorHistoryProducer is not what is expected";
00233                   
00234                   cout << "Particle : " << *p << endl;
00235                   cout << "Parents : " << endl;
00236                   vector<Candidate const *>::const_iterator iprint = allParents.begin(),
00237                     iprintend = allParents.end();
00238                   for ( ; iprint != iprintend; ++iprint ) 
00239                     cout << **iprint << endl;
00240 
00241                   foundProgenitor = false;
00242 
00243                 }
00244               } 
00245               // Here we have a gluon splitting from final state radiation. 
00246               // The parent is a quark of a different flavor, or a gluon, in the
00247               // final state. 
00248               else if( (aParentId > 0 && aParentId < FlavorHistory::tQuarkId ) || aParentId==FlavorHistory::gluonId ) {
00249                 if(verbose_) cout << "Gluon splitting progenitor" << endl;
00250                 flavorSource = FlavorHistory::FLAVOR_GS;
00251                 foundProgenitor = true;
00252               }
00253               // Here we have a true decay. Parent is not a quark or a gluon.
00254               else if( (aParentId>pdgIdToSelect_ && aParentId<FlavorHistory::gluonId) || aParentId > FlavorHistory::gluonId ) {
00255                 if(verbose_) cout << "Flavor decay progenitor" << endl;
00256                 flavorSource = FlavorHistory::FLAVOR_DECAY;
00257                 foundProgenitor = true;
00258               }
00259             }
00260 
00261             // -----------------------------------------------------------------------
00262             // Here we examine particles that were produced before the collision
00263             // -----------------------------------------------------------------------
00264             else if( progenitorIndex <= 5 ) {
00265               // Parent has a quark daughter equal and opposite to this: ISR
00266               if( aParent->numberOfDaughters() > 0 && 
00267                   aParent->daughter(0)->pdgId() == -1 * p->pdgId()  ) {
00268                 if(verbose_) cout << "Gluon splitting progenitor" << endl;
00269                 flavorSource = FlavorHistory::FLAVOR_GS;
00270               }
00271               // Otherwise, this is flavor excitation. Rarely happens because
00272               // mostly the initial state is gluons which will be caught by the
00273               // "matrix element" version above. 
00274               else {              
00275                 if(verbose_) cout << "Flavor excitation progenitor" << endl;
00276                 flavorSource = FlavorHistory::FLAVOR_EXC;
00277               }
00278               foundProgenitor = true;
00279             }
00280           }// End loop over all parents of this parton to find progenitor
00281 
00282             
00283 
00284           // 
00285           // Now find sister of this particle if there is one
00286           // 
00287           if ( foundProgenitor && progenitorIndex >= 0 ) {
00288             // Get the progenitor
00289             const Candidate * progenitorCand = particles[progenitorIndex];
00290 
00291             if ( verbose_ ) cout << "Found progenitor: " << *progenitorCand << endl;
00292 
00293             // Here is the normal case of a sister around
00294             if ( progenitorCand->numberOfDaughters() >= 2 ) {
00295               const Candidate * sisterCand = 0;
00296               
00297               for ( unsigned int iida = 0; iida < progenitorCand->numberOfDaughters(); ++iida ) {
00298                 const Candidate * dai = progenitorCand->daughter(iida);
00299 
00300                 if ( verbose_ ) cout << "Sister candidate " << *dai << endl;
00301                 
00302                 if ( dai->pdgId() == -1 * p->pdgId() ) {
00303                   if ( verbose_ ) cout << "Found actual sister" << endl;
00304                   sisterCand = dai;
00305                   foundSister = true;
00306                 }
00307               }
00308                 
00309               if ( foundSister ) {
00310                 // Find index of daughter in master list
00311                 vector<Candidate const *>::const_iterator found = find(particles.begin(),particles.end(),sisterCand);
00312                 sisterIndex = found - particles.begin();
00313                 if(verbose_) cout << "Sister index = " << sisterIndex << endl;
00314                 if ( found != particles.end() )
00315                   if(verbose_) cout << "Sister = " << **found << endl;
00316               } // end if found sister
00317             }
00318             // Here is if we have a "transient" decay in the code that isn't
00319             // really a decay, so we need to look at the parent of the progenitor
00320             else {
00321               const Candidate * grandProgenitorCand = progenitorCand->mother(0);
00322               const Candidate * sisterCand = 0;
00323 
00324               if ( verbose_ ) cout << "Looking for sister, progenitor is " << *progenitorCand << endl;
00325             
00326               // Make sure the progenitor has two daughters
00327               if ( grandProgenitorCand->numberOfDaughters() >= 2 ) {
00328 
00329                 for ( unsigned int iida = 0; iida < grandProgenitorCand->numberOfDaughters(); ++iida ) {
00330                   const Candidate * dai = grandProgenitorCand->daughter(iida);
00331 
00332                   if ( verbose_ ) cout << "Looking for sister " << *dai << endl;
00333                 
00334                   if ( dai->pdgId() == -1 * p->pdgId() ) {
00335                     if ( verbose_ ) cout << "Found sister" << endl;
00336                     sisterCand = dai;
00337                     foundSister = true;
00338                   }
00339                 }
00340                 
00341                 if ( foundSister ) {
00342                   // Find index of daughter in master list
00343                   vector<Candidate const *>::const_iterator found = find(particles.begin(),particles.end(),sisterCand);
00344                   sisterIndex = found - particles.begin();
00345                   if(verbose_) cout << "Sister index = " << sisterIndex << endl;
00346                   if ( found != particles.end() )
00347                     if(verbose_) cout << "Sister = " << **found << endl;
00348                 } // end if found sister
00349               } // End of have at least 2 grand progenitor daughters
00350             } // End if we have to look at parents of progenitor to find sister
00351 
00352           } // end if found progenitor
00353 
00354           // ------
00355           // Here, we change the type from matrix element to flavor excitation
00356           // if there are no sisters present. 
00357           // ------
00358           if ( flavorSource == FlavorHistory::FLAVOR_ME && !foundSister ) {
00359             flavorSource = FlavorHistory::FLAVOR_EXC;
00360           }
00361           
00362         }// End if this parton passes some minimal kinematic cuts
00363       }// End if this particle has strings as daughters
00364     }// End if this particle was a status==2 parton
00365 
00366     // Make sure we've actually found a sister and a progenitor
00367     if ( !foundProgenitor ) progenitorIndex = 0;
00368     if ( !foundSister ) sisterIndex = 0;
00369 
00370     // We've found the particle, add to the list (status 2 only)
00371     if ( idabs == pdgIdToSelect_ && p->status() == 2 ) 
00372       flavorHistoryVector->push_back( FlavorHistory( flavorSource, particlesViewH, partonIndex, progenitorIndex, sisterIndex ) ); 
00373   }
00374 
00375 
00376 //   ValueMap<FlavorHistory>::Filler filler(*flavorHistory);
00377 //   filler.insert( particlesViewH, flavorHistoryVector.begin(), flavorHistoryVector.end()  );
00378 //   filler.fill();
00379   // Now add the flavor history to the event record
00380   if ( verbose_ ) {
00381     cout << "Outputting pdg id = " << pdgIdToSelect_ << " with nelements = " << flavorHistoryVector->size() << endl;
00382     vector<FlavorHistory>::const_iterator i = flavorHistoryVector->begin(),
00383       iend = flavorHistoryVector->end();
00384     for ( ; i !=iend; ++i ) {
00385       cout << *i << endl;
00386     }
00387   }
00388   evt.put( flavorHistoryVector, flavorHistoryName_ );
00389 }
00390 
00391  
00392 // Helper function to get all ancestors of this candidate
00393 void FlavorHistoryProducer::getAncestors(const Candidate &c,
00394                                          vector<Candidate const *> & moms )
00395 {
00396 
00397   if( c.numberOfMothers() == 1 ) {
00398     const Candidate * dau = &c;
00399     const Candidate * mom = c.mother();
00400     while ( dau->numberOfMothers() != 0) {
00401       moms.push_back( dau );
00402       dau = mom ;
00403       mom = dau->mother();
00404     } 
00405   } 
00406 }
00407 
00408 
00409 
00410 #include "FWCore/Framework/interface/MakerMacros.h"
00411 
00412 DEFINE_FWK_MODULE( FlavorHistoryProducer );

Generated on Tue Jun 9 17:41:06 2009 for CMSSW by  doxygen 1.5.4