CMS 3D CMS Logo

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