CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/TopQuarkAnalysis/TopSkimming/src/TtDecayChannelSelector.cc

Go to the documentation of this file.
00001 #include "FWCore/Utilities/interface/EDMException.h"
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003 #include "AnalysisDataFormats/TopObjects/interface/TopGenEvent.h"
00004 #include "TopQuarkAnalysis/TopSkimming/interface/TtDecayChannelSelector.h"
00005 
00006 // static const string for status check in  
00007 // TtDecayChannelSelector::search functions
00008 static const std::string kGenParticles = "genParticles";
00009 
00010 // number of top branches for decay selection
00011 static const unsigned int kTopBranches   = 2;
00012 
00013 // maximal number of possible leptonic decay 
00014 // channels
00015 static const unsigned int kDecayChannels = 3;
00016 
00017 
00018 TtDecayChannelSelector::TtDecayChannelSelector(const edm::ParameterSet& cfg):
00019   invert_ ( cfg.getParameter<bool>("invert" ) ),
00020   allowLepton_(false), allow1Prong_(false), 
00021   allow3Prong_(false)
00022 {
00023   // tau decays are not restricted if this PSet does not exist at all
00024   restrictTauDecays_=cfg.existsAs<edm::ParameterSet>("restrictTauDecays");
00025   // determine allowed tau decays
00026   if(restrictTauDecays_){
00027     edm::ParameterSet allowedTauDecays = cfg.getParameter<edm::ParameterSet>("restrictTauDecays");
00028     // tau decays are not restricted if none of the following parameters exists
00029     restrictTauDecays_=(allowedTauDecays.existsAs<bool>("leptonic"  )|| 
00030                         allowedTauDecays.existsAs<bool>("oneProng"  )|| 
00031                         allowedTauDecays.existsAs<bool>("threeProng") );
00032     // specify the different possible restrictions of the tau decay channels
00033     allowLepton_ = (allowedTauDecays.existsAs<bool>("leptonic"  ) ? allowedTauDecays.getParameter<bool>("leptonic"  ) : false); 
00034     allow1Prong_ = (allowedTauDecays.existsAs<bool>("oneProng"  ) ? allowedTauDecays.getParameter<bool>("oneProng"  ) : false); 
00035     allow3Prong_ = (allowedTauDecays.existsAs<bool>("threeProng") ? allowedTauDecays.getParameter<bool>("threeProng") : false);
00036   }
00037   // allowed top decays PSet
00038   edm::ParameterSet allowedTopDecays = cfg.getParameter<edm::ParameterSet>("allowedTopDecays");
00039 
00040   // fill decayBranchA_
00041   edm::ParameterSet decayBranchA = allowedTopDecays.getParameter<edm::ParameterSet>("decayBranchA");
00042   decayBranchA_.push_back(decayBranchA.getParameter<bool>("electron"));
00043   decayBranchA_.push_back(decayBranchA.getParameter<bool>("muon"    ));
00044   decayBranchA_.push_back(decayBranchA.getParameter<bool>("tau"     ));
00045 
00046   // fill decay branchB_
00047   edm::ParameterSet decayBranchB = allowedTopDecays.getParameter<edm::ParameterSet>("decayBranchB");
00048   decayBranchB_.push_back(decayBranchB.getParameter<bool>("electron"));
00049   decayBranchB_.push_back(decayBranchB.getParameter<bool>("muon"    ));
00050   decayBranchB_.push_back(decayBranchB.getParameter<bool>("tau"     ));
00051 
00052   // fill allowedDecays_
00053   for(unsigned int d=0; d<kDecayChannels; ++d){
00054     allowedDecays_.push_back(decayBranchA_[d]+decayBranchB_[d]);
00055   }
00056 }
00057 
00058 TtDecayChannelSelector::~TtDecayChannelSelector()
00059 { 
00060 } 
00061 
00062 bool
00063 TtDecayChannelSelector::operator()(const reco::GenParticleCollection& parts, std::string inputType) const
00064 {
00065   bool verbose=false; // set this to true for debugging and add TtDecayChannelSelector category to the MessageLogger in your cfg file
00066   unsigned int iLep=0;
00067   unsigned int iTop=0,iBeauty=0,iElec=0,iMuon=0,iTau=0;
00068   for(reco::GenParticleCollection::const_iterator top=parts.begin(); top!=parts.end(); ++top){
00069     if( search(top, TopDecayID::tID, inputType) ){
00070       ++iTop;
00071       for(reco::GenParticle::const_iterator td=top->begin(); td!=top->end(); ++td){
00072         if( search(td, TopDecayID::bID, inputType) ){
00073           ++iBeauty;
00074         }
00075         if( search(td, TopDecayID::WID, inputType) ){
00076           for(reco::GenParticle::const_iterator wd=td->begin(); wd!=td->end(); ++wd){
00077             if( std::abs(wd->pdgId())==TopDecayID::elecID ){
00078               ++iElec;
00079             }
00080             if( std::abs(wd->pdgId())==TopDecayID::muonID ){
00081               ++iMuon;
00082             }
00083             if( std::abs(wd->pdgId())==TopDecayID::tauID  ){ 
00084               if(restrictTauDecays_){
00085                 // count as iTau if it is leptonic, one-prong
00086                 // or three-prong and ignore increasing iLep
00087                 // though else
00088                 if(tauDecay(*wd)){
00089                   ++iTau; 
00090                 } else{
00091                   ++iLep; 
00092                 }
00093               }
00094               else{
00095                 ++iTau;
00096               }
00097             }
00098           }
00099         }
00100       }
00101     }
00102   }
00103   if(verbose) {
00104     edm::LogVerbatim log("TtDecayChannelSelector");
00105     log << "----------------------"   << "\n"
00106         << " iTop    : " << iTop      << "\n"
00107         << " iBeauty : " << iBeauty   << "\n"
00108         << " iElec   : " << iElec     << "\n"
00109         << " iMuon   : " << iMuon     << "\n"
00110         << " iTau    : " << iTau+iLep;
00111     if(restrictTauDecays_ && (iTau+iLep)>0){
00112       log << " (" << iTau << ")\n";
00113     }
00114     else{
00115       log << "\n";
00116     }
00117     log << "- - - - - - - - - - - "   << "\n";
00118   }
00119   iLep+=iElec+iMuon+iTau;
00120 
00121   bool accept=false;
00122   unsigned int channel = decayChannel();
00123   if( (iTop==2) && (iBeauty==2) ){
00124     if( channel==iLep ){
00125       if( channel==0 ){
00126         // no lepton: accept without restriction we already 
00127         // know that the number of leptons is correct
00128         accept=true;
00129       }
00130       if( channel==1 ){
00131         // one lepton: check that this one is allowed
00132         accept=(iElec&&allowedDecays_[Elec]) || (iMuon&&allowedDecays_[Muon]) || (iTau&&allowedDecays_[Tau]);
00133       }
00134       if( channel==2 ){
00135         if( checkSum(allowedDecays_)==channel ){
00136           // no redundancy
00137           accept = (allowedDecays_[Elec]==(int)iElec) && (allowedDecays_[Muon]==(int)iMuon) && (allowedDecays_[Tau]==(int)iTau);
00138         }
00139         else{
00140           // reject events with wrong tau decays
00141           if(iElec+iMuon+iTau!=channel){
00142             accept = false;
00143           }
00144           else {
00145             if((iElec==2)||(iMuon==2)||(iTau==2)) {
00146               // same lepton twice: check that this is allowed.
00147               accept = (allowedDecays_[Elec]==(int)iElec)||(allowedDecays_[Muon]==(int)iMuon)||(allowedDecays_[Tau]==(int)iTau);
00148             } 
00149             else {
00150               // two different leptons: look if there is a possible combination
00151               accept = ( ((iElec&&decayBranchA_[Elec])&&((iMuon&&decayBranchB_[Muon])||(iTau &&decayBranchB_[Tau ]))) ||
00152                          ((iMuon&&decayBranchA_[Muon])&&((iElec&&decayBranchB_[Elec])||(iTau &&decayBranchB_[Tau ]))) ||
00153                          ((iTau &&decayBranchA_[Tau ])&&((iElec&&decayBranchB_[Elec])||(iMuon&&decayBranchB_[Muon])))   );
00154             }
00155           }
00156         }
00157       }
00158     }
00159     accept=( (!invert_&& accept) || (!(!invert_)&& !accept) );
00160   }
00161   else{
00162     edm::LogWarning ( "NoVtbDecay" ) << "Decay is not via Vtb";
00163   }
00164   if(verbose)
00165     edm::LogVerbatim("TtDecayChannelSelector") << " accept  : " << accept;
00166   return accept;
00167 }
00168 
00169 bool
00170 TtDecayChannelSelector::search(reco::GenParticleCollection::const_iterator& part, int pdgId, std::string& inputType) const
00171 {
00172   if(inputType==kGenParticles){
00173     return (std::abs(part->pdgId())==pdgId && part->status()==TopDecayID::unfrag) ? true : false;
00174   }
00175   else{
00176     return (std::abs(part->pdgId())==pdgId) ? true : false;
00177   }
00178 }
00179 
00180 bool
00181 TtDecayChannelSelector::search(reco::GenParticle::const_iterator& part, int pdgId, std::string& inputType) const
00182 {
00183   if(inputType==kGenParticles){
00184     return (std::abs(part->pdgId())==pdgId && part->status()==TopDecayID::unfrag) ? true : false;
00185   }
00186   else{
00187     return (std::abs(part->pdgId())==pdgId) ? true : false;
00188   }
00189 }
00190 
00191 unsigned int 
00192 TtDecayChannelSelector::countProngs(const reco::Candidate& part) const
00193 {
00194   // if stable, return 1 or 0
00195   if(part.status()==1){
00196     return (part.charge()!=0);
00197   }
00198   // if unstable, call recursively on daughters
00199   int prong =0;
00200   for(reco::Candidate::const_iterator daughter=part.begin();daughter!=part.end(); ++daughter){
00201     prong += countProngs(*daughter);
00202   }
00203   return prong;
00204 }
00205 
00206 bool
00207 TtDecayChannelSelector::tauDecay(const reco::Candidate& tau) const
00208 {
00209   bool leptonic = false;
00210   unsigned int nch = 0;
00211   // loop on tau decays, check for an elec
00212   // or muon and count charged particles
00213   for(reco::Candidate::const_iterator daughter=tau.begin();daughter!=tau.end(); ++daughter){
00214     // if the tau daughter is again a tau, this means that the particle has 
00215     // still to be propagated; in that case, return the result of the same 
00216     // method applied on the daughter of the current particle
00217     if(daughter->pdgId()==tau.pdgId()){
00218       return tauDecay(*daughter);
00219     }
00220     // check for leptons
00221     leptonic |= (std::abs(daughter->pdgId())==TopDecayID::elecID || std::abs(daughter->pdgId())==TopDecayID::muonID);
00222     // count charged particles
00223     nch += countProngs(*daughter);
00224   }
00225   return ((allowLepton_ &&  leptonic)          ||
00226           (allow1Prong_ && !leptonic && nch==1)||
00227           (allow3Prong_ && !leptonic && nch==3));
00228 }