CMS 3D CMS Logo

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/TtGenEvent.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 {
00021   // determine allowed tauy decays
00022   edm::ParameterSet allowedTauDecays = cfg.getParameter<edm::ParameterSet>("allowedTauDecays");
00023   allowLepton_ = allowedTauDecays.getParameter<bool>("leptonic"); 
00024   allow1Prong_ = allowedTauDecays.getParameter<bool>("oneProng"); 
00025   allow3Prong_ = allowedTauDecays.getParameter<bool>("threeProng");
00026 
00027   // allowed top decays PSet
00028   edm::ParameterSet allowedTopDecays = cfg.getParameter<edm::ParameterSet>("allowedTopDecays");
00029 
00030   // fill decayBranchA_
00031   edm::ParameterSet decayBranchA = allowedTopDecays.getParameter<edm::ParameterSet>("decayBranchA");
00032   decayBranchA_.push_back(decayBranchA.getParameter<bool>("electron"));
00033   decayBranchA_.push_back(decayBranchA.getParameter<bool>("muon"    ));
00034   decayBranchA_.push_back(decayBranchA.getParameter<bool>("tau"     ));
00035 
00036   // fill decay branchB_
00037   edm::ParameterSet decayBranchB = allowedTopDecays.getParameter<edm::ParameterSet>("decayBranchB");
00038   decayBranchB_.push_back(decayBranchB.getParameter<bool>("electron"));
00039   decayBranchB_.push_back(decayBranchB.getParameter<bool>("muon"    ));
00040   decayBranchB_.push_back(decayBranchB.getParameter<bool>("tau"     ));
00041 
00042   // fill allowedDecays_
00043   for(unsigned int d=0; d<kDecayChannels; ++d){
00044     allowedDecays_.push_back(decayBranchA_[d]+decayBranchB_[d]);
00045   }
00046 }
00047 
00048 TtDecayChannelSelector::~TtDecayChannelSelector()
00049 { 
00050 } 
00051 
00052 bool
00053 TtDecayChannelSelector::operator()(const reco::GenParticleCollection& parts, std::string inputType) const
00054 {
00055   unsigned int iLep=0;
00056   unsigned int iTop=0,iBeauty=0,iElec=0,iMuon=0,iTau=0;
00057   for(reco::GenParticleCollection::const_iterator top=parts.begin(); top!=parts.end(); ++top){
00058     if( search(top, TopDecayID::tID, inputType) ){
00059       ++iTop;
00060       for(reco::GenParticle::const_iterator td=top->begin(); td!=top->end(); ++td){
00061         if( search(td, TopDecayID::bID, inputType) ){
00062           ++iBeauty;
00063         }
00064         if( search(td, TopDecayID::WID, inputType) ){
00065           for(reco::GenParticle::const_iterator wd=td->begin(); wd!=td->end(); ++wd){
00066             if( abs(wd->pdgId())==TopDecayID::elecID ){
00067               ++iElec;
00068             }
00069             if( abs(wd->pdgId())==TopDecayID::muonID ){
00070               ++iMuon;
00071             }
00072             if( abs(wd->pdgId())==TopDecayID::tauID  ){ 
00073               // count as iTau if it is leptonic, one-prong
00074               // or three-prong and ignore increasing iLep
00075               // though else
00076               if(tauDecay(*wd)){
00077                 ++iTau; 
00078               } else{
00079                 ++iLep; 
00080               }
00081             }
00082           }
00083         }
00084       }
00085     }
00086   }
00087   edm::LogVerbatim log("TtDecayChannelSelector::selection");
00088   log << "----------------------" << "\n"
00089       << " iTop    : " << iTop    << "\n"
00090       << " iBeauty : " << iBeauty << "\n"
00091       << " iElec   : " << iElec   << "\n"
00092       << " iMuon   : " << iMuon   << "\n"
00093       << " iTau    : " << iTau    << "\n"
00094       << "- - - - - - - - - - - " << "\n";
00095   iLep+=iElec+iMuon+iTau;
00096 
00097   bool accept=false;
00098   unsigned int channel = decayChannel();
00099   if( (iTop==2) && (iBeauty==2) ){
00100     if( channel==iLep ){
00101       if( channel==0 ){
00102         // no lepton: accept without restriction we already 
00103         // know that the number of leptons is correct
00104         accept=true;
00105       }
00106       if( channel==1 ){
00107         // one lepton: check that this one is allowed
00108         accept=(iElec&&allowedDecays_[Elec]) || (iMuon&&allowedDecays_[Muon]) || (iTau&&allowedDecays_[Tau]);
00109       }
00110       if( channel==2 ){
00111         if( checkSum(allowedDecays_)==channel ){
00112           // no redundancy
00113           accept = (allowedDecays_[Elec]==(int)iElec) && (allowedDecays_[Muon]==(int)iMuon) && (allowedDecays_[Tau]==(int)iTau);
00114         }
00115         else{
00116           // reject events with wrong tau decays
00117           if(iElec+iMuon+iTau!=channel){
00118             accept = false;
00119           }
00120           else {
00121             if((iElec==2)||(iMuon==2)||(iTau==2)) {
00122               // same lepton twice: check that this is allowed.
00123               accept = (allowedDecays_[Elec]==(int)iElec)||(allowedDecays_[Muon]==(int)iMuon)||(allowedDecays_[Tau]==(int)iTau);
00124             } 
00125             else {
00126               // two different leptons: look if there is a possible combination
00127               accept = ( ((iElec&&decayBranchA_[Elec])&&((iMuon&&decayBranchB_[Muon])||(iTau &&decayBranchB_[Tau ]))) ||
00128                          ((iMuon&&decayBranchA_[Muon])&&((iElec&&decayBranchB_[Elec])||(iTau &&decayBranchB_[Tau ]))) ||
00129                          ((iTau &&decayBranchA_[Tau ])&&((iElec&&decayBranchB_[Elec])||(iMuon&&decayBranchB_[Muon])))   );
00130             }
00131           }
00132         }
00133       }
00134     }
00135     accept=( (!invert_&& accept) || (!(!invert_)&& !accept) );
00136   }
00137   else{
00138     edm::LogWarning ( "NoVtbDecay" ) << "Decay is not via Vtb";
00139   }
00140   log << " accept  : " << accept;
00141   return accept;
00142 }
00143 
00144 bool
00145 TtDecayChannelSelector::search(reco::GenParticleCollection::const_iterator& part, int pdgId, std::string& inputType) const
00146 {
00147   if(inputType==kGenParticles){
00148     return (abs(part->pdgId())==pdgId && part->status()==TopDecayID::unfrag) ? true : false;
00149   }
00150   else{
00151     return (abs(part->pdgId())==pdgId) ? true : false;
00152   }
00153 }
00154 
00155 bool
00156 TtDecayChannelSelector::search(reco::GenParticle::const_iterator& part, int pdgId, std::string& inputType) const
00157 {
00158   if(inputType==kGenParticles){
00159     return (abs(part->pdgId())==pdgId && part->status()==TopDecayID::unfrag) ? true : false;
00160   }
00161   else{
00162     return (abs(part->pdgId())==pdgId) ? true : false;
00163   }
00164 }
00165 
00166 unsigned int 
00167 TtDecayChannelSelector::countProngs(const reco::Candidate& part) const
00168 {
00169   // if stable, return 1 or 0
00170   if(part.status()==TopDecayID::stable){
00171     return (part.charge()!=0);
00172   }
00173   // if unstable, call recursively on daughters
00174   int prong =0;
00175   for(reco::Candidate::const_iterator daughter=part.begin();daughter!=part.end(); ++daughter){
00176     prong += countProngs(*daughter);
00177   }
00178   return prong;
00179 }
00180 
00181 bool
00182 TtDecayChannelSelector::tauDecay(const reco::Candidate& tau) const
00183 {
00184   bool leptonic = false;
00185   unsigned int nch = 0;
00186   // loop on tau decays, check for an elec
00187   // or muon and count charged particles
00188   for(reco::Candidate::const_iterator daughter=tau.begin();daughter!=tau.end(); ++daughter){
00189     // if the tau daughter is again a tau, this means that the particle has 
00190     // still to be propagated; in that case, return the result of the same 
00191     // method applied on the on that daughter
00192     if(daughter->pdgId()==tau.pdgId()){
00193       return tauDecay(*daughter);
00194     }
00195     // check for leptons
00196     leptonic |= (abs(daughter->pdgId())==TopDecayID::elecID || abs(daughter->pdgId())==TopDecayID::muonID);
00197     // count charged particles
00198     nch += countProngs(*daughter);
00199   }
00200   return ((allowLepton_ &&  leptonic)          ||
00201           (allow1Prong_ && !leptonic && nch==1)||
00202           (allow3Prong_ && !leptonic && nch >1));
00203 }

Generated on Tue Jun 9 17:48:15 2009 for CMSSW by  doxygen 1.5.4