CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/TopQuarkAnalysis/TopKinFitter/plugins/TtFullLepKinSolutionProducer.h

Go to the documentation of this file.
00001 #ifndef TtFullLepKinSolutionProducer_h
00002 #define TtFullLepKinSolutionProducer_h
00003 
00004 //
00005 // $Id: TtFullLepKinSolutionProducer.h,v 1.10 2010/12/02 10:48:13 snaumann Exp $
00006 //
00007 #include <memory>
00008 #include <string>
00009 #include <vector>
00010 #include "TLorentzVector.h"
00011 #include "DataFormats/Math/interface/deltaR.h"
00012 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00013 #include "FWCore/Framework/interface/EDProducer.h"
00014 #include "FWCore/Framework/interface/Event.h"
00015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00016 #include "FWCore/Utilities/interface/InputTag.h"
00017 #include "DataFormats/Candidate/interface/LeafCandidate.h"
00018 #include "TopQuarkAnalysis/TopKinFitter/interface/TtFullLepKinSolver.h"
00019 
00020 
00021 class TtFullLepKinSolutionProducer : public edm::EDProducer {
00022 
00023   public:
00024 
00025     explicit TtFullLepKinSolutionProducer(const edm::ParameterSet & iConfig);
00026     ~TtFullLepKinSolutionProducer();
00027     
00028     virtual void beginJob();
00029     virtual void produce(edm::Event & evt, const edm::EventSetup & iSetup);
00030     virtual void endJob();
00031 
00032   private:  
00033 
00034     // next methods are avoidable but they make the code legible
00035     inline bool PTComp(const reco::Candidate*, const reco::Candidate*) const;
00036     inline bool LepDiffCharge(const reco::Candidate* , const reco::Candidate*) const;
00037     inline bool HasPositiveCharge(const reco::Candidate*) const;
00038     
00039     struct Compare{
00040       bool operator()(std::pair<double, int> a, std::pair<double, int> b){
00041         return a.first > b.first;
00042       } 
00043     };
00044     
00045     edm::InputTag jets_;
00046     edm::InputTag electrons_;
00047     edm::InputTag muons_;
00048     edm::InputTag mets_;
00049 
00050     std::string jetCorrLevel_;
00051     int maxNJets_, maxNComb_;
00052     bool eeChannel_, emuChannel_, mumuChannel_, searchWrongCharge_;
00053     double tmassbegin_, tmassend_, tmassstep_;
00054     std::vector<double> nupars_;
00055     
00056     TtFullLepKinSolver* solver;
00057 };
00058 
00059 inline bool TtFullLepKinSolutionProducer::PTComp(const reco::Candidate* l1, const reco::Candidate* l2) const 
00060 {
00061   return (l1->pt() > l2->pt());
00062 }
00063 
00064 inline bool TtFullLepKinSolutionProducer::LepDiffCharge(const reco::Candidate* l1, const reco::Candidate* l2) const 
00065 {
00066   return (l1->charge() != l2->charge());
00067 }
00068 
00069 inline bool TtFullLepKinSolutionProducer::HasPositiveCharge(const reco::Candidate* l) const 
00070 {
00071   return (l->charge() > 0);
00072 }
00073 
00074 TtFullLepKinSolutionProducer::TtFullLepKinSolutionProducer(const edm::ParameterSet & iConfig) 
00075 {
00076   // configurables
00077   jets_        = iConfig.getParameter<edm::InputTag>("jets");
00078   electrons_   = iConfig.getParameter<edm::InputTag>("electrons");
00079   muons_       = iConfig.getParameter<edm::InputTag>("muons");
00080   mets_        = iConfig.getParameter<edm::InputTag>("mets");
00081   jetCorrLevel_= iConfig.getParameter<std::string>  ("jetCorrectionLevel");  
00082   maxNJets_       = iConfig.getParameter<int> ("maxNJets");
00083   maxNComb_       = iConfig.getParameter<int> ("maxNComb");  
00084   eeChannel_      = iConfig.getParameter<bool>("eeChannel"); 
00085   emuChannel_     = iConfig.getParameter<bool>("emuChannel");
00086   mumuChannel_    = iConfig.getParameter<bool>("mumuChannel");
00087   searchWrongCharge_ = iConfig.getParameter<bool> ("searchWrongCharge");  
00088   tmassbegin_       = iConfig.getParameter<double>("tmassbegin");
00089   tmassend_         = iConfig.getParameter<double>("tmassend");
00090   tmassstep_        = iConfig.getParameter<double>("tmassstep");
00091   nupars_           = iConfig.getParameter<std::vector<double> >("neutrino_parameters");
00092   
00093   // define what will be produced
00094   produces<std::vector<std::vector<int> > >  (); // vector of the particle inices (b, bbar, e1, e2, mu1, mu2)
00095   produces<std::vector<reco::LeafCandidate> >("fullLepNeutrinos");  
00096   produces<std::vector<reco::LeafCandidate> >("fullLepNeutrinoBars");        
00097   produces<std::vector<double> >("solWeight");          //weight for a specific kin solution 
00098   produces<bool>("isWrongCharge");                      //true if leptons have the same charge    
00099 }
00100 
00101 TtFullLepKinSolutionProducer::~TtFullLepKinSolutionProducer() 
00102 {
00103 }
00104 
00105 void TtFullLepKinSolutionProducer::beginJob()
00106 {
00107   solver = new TtFullLepKinSolver(tmassbegin_, tmassend_, tmassstep_, nupars_);
00108 }
00109 
00110 void TtFullLepKinSolutionProducer::endJob()
00111 {
00112   delete solver;
00113 }
00114 
00115 void TtFullLepKinSolutionProducer::produce(edm::Event & evt, const edm::EventSetup & iSetup) 
00116 {    
00117   //create vectors fo runsorted output
00118   std::vector<std::vector<int> > idcsV;
00119   std::vector<reco::LeafCandidate> nusV;
00120   std::vector<reco::LeafCandidate> nuBarsV;
00121   std::vector<std::pair<double, int> > weightsV;
00122 
00123   //create pointer for products
00124   std::auto_ptr<std::vector<std::vector<int> > >   pIdcs(new std::vector<std::vector<int> >);
00125   std::auto_ptr<std::vector<reco::LeafCandidate> > pNus(new std::vector<reco::LeafCandidate>);
00126   std::auto_ptr<std::vector<reco::LeafCandidate> > pNuBars(new std::vector<reco::LeafCandidate>);
00127   std::auto_ptr<std::vector<double> >              pWeight(new std::vector<double>);  
00128   std::auto_ptr<bool> pWrongCharge(new bool);  
00129     
00130   edm::Handle<std::vector<pat::Jet> > jets;
00131   evt.getByLabel(jets_, jets);
00132   edm::Handle<std::vector<pat::Electron> > electrons;
00133   evt.getByLabel(electrons_, electrons);
00134   edm::Handle<std::vector<pat::Muon> > muons;
00135   evt.getByLabel(muons_, muons);
00136   edm::Handle<std::vector<pat::MET> > mets;
00137   evt.getByLabel(mets_, mets);
00138   
00139   int selMuon1 = -1, selMuon2 = -1;
00140   int selElectron1 = -1, selElectron2 = -1;
00141   bool ee = false;
00142   bool emu = false;
00143   bool mumu = false;
00144   bool isWrongCharge = false;
00145   bool jetsFound = false;
00146   bool METFound = false;
00147   bool electronsFound = false;
00148   bool electronMuonFound = false;
00149   bool muonsFound = false;
00150   
00151   //select Jets (TopJet vector is sorted on ET)
00152   if(jets->size()>=2) { jetsFound = true; }  
00153   
00154   //select MET (TopMET vector is sorted on ET)
00155   if(mets->size()>=1) { METFound = true; }
00156   
00157   // If we have electrons and muons available, 
00158   // build a solutions with electrons and muons.
00159   if(muons->size() + electrons->size() >=2) {     
00160     // select leptons
00161     if(electrons->size() == 0) mumu = true;
00162     else if(muons->size() == 0) ee = true;
00163     else if(electrons->size() == 1) {
00164       if(muons->size() == 1) emu = true;
00165       else if(PTComp(&(*electrons)[0], &(*muons)[1])) emu = true;
00166       else mumu = true;
00167     }
00168     else if(electrons->size() > 1) {
00169       if(PTComp(&(*electrons)[1], &(*muons)[0])) ee = true;
00170       else if(muons->size() == 1) emu = true;
00171       else if(PTComp(&(*electrons)[0], &(*muons)[1])) emu = true;
00172       else mumu = true;
00173     }
00174     if(ee && eeChannel_) {          
00175       if(LepDiffCharge(&(*electrons)[0], &(*electrons)[1]) || searchWrongCharge_) {
00176         if(HasPositiveCharge(&(*electrons)[0]) || !LepDiffCharge(&(*electrons)[0], &(*electrons)[1])) {
00177           selElectron1 = 0;
00178           selElectron2 = 1;
00179         } 
00180         else{
00181           selElectron1 = 1;
00182           selElectron2 = 0;
00183         }
00184         electronsFound = true;
00185         if(!LepDiffCharge(&(*electrons)[0], &(*electrons)[1])) isWrongCharge = true;
00186       }
00187     }
00188     else if(emu && emuChannel_) {    
00189       if(LepDiffCharge(&(*electrons)[0], &(*muons)[0]) || searchWrongCharge_) {
00190         selElectron1 = 0;
00191         selMuon1 = 0;
00192         electronMuonFound = true;
00193         if(!LepDiffCharge(&(*electrons)[0], &(*muons)[0])) isWrongCharge = true;
00194       }
00195     }
00196     else if(mumu && mumuChannel_) {  
00197       if(LepDiffCharge(&(*muons)[0], &(*muons)[1]) || searchWrongCharge_) {
00198         if(HasPositiveCharge(&(*muons)[0]) || !LepDiffCharge(&(*muons)[0], &(*muons)[1])) {
00199           selMuon1 = 0;
00200           selMuon2 = 1;
00201         } 
00202         else {
00203           selMuon1 = 1;
00204           selMuon2 = 0;
00205         }
00206         muonsFound = true;
00207         if(!LepDiffCharge(&(*muons)[0], &(*muons)[1])) isWrongCharge = true;
00208       }
00209     }
00210   }
00211   
00212   *pWrongCharge = isWrongCharge;
00213    
00214   // Check that the above work makes sense
00215   if(int(ee)+int(emu)+int(mumu)>1) {
00216     edm::LogWarning("TtFullLepKinSolutionProducer") << "Lepton selection criteria uncorrectly defined";
00217   }
00218     
00219   // Check if the leptons for the required Channel are available
00220   bool correctLeptons = ((electronsFound && eeChannel_) || (muonsFound && mumuChannel_) || (electronMuonFound && emuChannel_) );
00221   // Check for equally charged leptons if for wrong charge combinations is searched
00222   if(isWrongCharge) correctLeptons *= searchWrongCharge_;       
00223                                           
00224   if(correctLeptons && METFound && jetsFound) { 
00225             
00226     // run over all jets if input parameter maxNJets is -1 or
00227     // adapt maxNJets if number of present jets is smaller than selected
00228     // number of jets    
00229     int stop=maxNJets_;
00230     if(jets->size()<static_cast<unsigned int>(stop) || stop<0) stop=jets->size();
00231        
00232     // counter for number of found kinematic solutions
00233     int nSol=0;
00234       
00235     // consider all permutations
00236     for (int ib = 0; ib<stop; ib++) {
00237       // second loop of the permutations
00238       for (int ibbar = 0; ibbar<stop; ibbar++) {
00239         // avoid the diagonal: b and bbar must be distinct jets
00240         if(ib==ibbar) continue;
00241                 
00242         std::vector<int> idcs;
00243         
00244         // push back the indices of the jets
00245         idcs.push_back(ib);
00246         idcs.push_back(ibbar);
00247 
00248         TLorentzVector LV_l1;
00249         TLorentzVector LV_l2;           
00250         TLorentzVector LV_b    = TLorentzVector((*jets)[ib].correctedJet(jetCorrLevel_, "bottom").px(), 
00251                                                 (*jets)[ib].correctedJet(jetCorrLevel_, "bottom").py(), 
00252                                                 (*jets)[ib].correctedJet(jetCorrLevel_, "bottom").pz(), 
00253                                                 (*jets)[ib].correctedJet(jetCorrLevel_, "bottom").energy() );
00254         TLorentzVector LV_bbar = TLorentzVector((*jets)[ibbar].correctedJet(jetCorrLevel_, "bottom").px(), 
00255                                                 (*jets)[ibbar].correctedJet(jetCorrLevel_, "bottom").py(), 
00256                                                 (*jets)[ibbar].correctedJet(jetCorrLevel_, "bottom").pz(), 
00257                                                 (*jets)[ibbar].correctedJet(jetCorrLevel_, "bottom").energy());  
00258                         
00259         double xconstraint = 0, yconstraint = 0;
00260         
00261         if (ee) {
00262           idcs.push_back(selElectron1);   
00263           LV_l1.SetXYZT((*electrons)[selElectron1].px(), 
00264                         (*electrons)[selElectron1].py(), 
00265                         (*electrons)[selElectron1].pz(), 
00266                         (*electrons)[selElectron1].energy());     
00267           xconstraint += (*electrons)[selElectron1].px();
00268           yconstraint += (*electrons)[selElectron1].py();       
00269         
00270           idcs.push_back(selElectron2);   
00271           LV_l2.SetXYZT((*electrons)[selElectron2].px(), 
00272                         (*electrons)[selElectron2].py(), 
00273                         (*electrons)[selElectron2].pz(), 
00274                         (*electrons)[selElectron2].energy());     
00275           xconstraint += (*electrons)[selElectron2].px();
00276           yconstraint += (*electrons)[selElectron2].py();
00277 
00278           idcs.push_back(-1);
00279           idcs.push_back(-1);
00280         } 
00281                                 
00282         else if (emu) {
00283           if(!isWrongCharge){
00284             if(HasPositiveCharge(&(*electrons)[selElectron1])){   
00285               idcs.push_back(selElectron1);       
00286               LV_l1.SetXYZT((*electrons)[selElectron1].px(), 
00287                             (*electrons)[selElectron1].py(), 
00288                             (*electrons)[selElectron1].pz(), 
00289                             (*electrons)[selElectron1].energy());         
00290               xconstraint += (*electrons)[selElectron1].px();
00291               yconstraint += (*electrons)[selElectron1].py();
00292 
00293               idcs.push_back(-1);
00294               idcs.push_back(-1);           
00295 
00296               idcs.push_back(selMuon1);   
00297               LV_l2.SetXYZT((*muons)[selMuon1].px(), 
00298                             (*muons)[selMuon1].py(), 
00299                             (*muons)[selMuon1].pz(), 
00300                             (*muons)[selMuon1].energy());         
00301               xconstraint += (*muons)[selMuon1].px();
00302               yconstraint += (*muons)[selMuon1].py();
00303             }
00304             else{
00305               idcs.push_back(-1);           
00306                 
00307               idcs.push_back(selMuon1);   
00308               LV_l1.SetXYZT((*muons)[selMuon1].px(), 
00309                             (*muons)[selMuon1].py(), 
00310                             (*muons)[selMuon1].pz(), 
00311                             (*muons)[selMuon1].energy());         
00312               xconstraint += (*muons)[selMuon1].px();
00313               yconstraint += (*muons)[selMuon1].py();
00314               
00315               idcs.push_back(selElectron1);       
00316               LV_l2.SetXYZT((*electrons)[selElectron1].px(), 
00317                             (*electrons)[selElectron1].py(), 
00318                             (*electrons)[selElectron1].pz(), 
00319                             (*electrons)[selElectron1].energy());         
00320               xconstraint += (*electrons)[selElectron1].px();
00321               yconstraint += (*electrons)[selElectron1].py();         
00322                   
00323               idcs.push_back(-1);                           
00324             }               
00325           }
00326           else{  // means "if wrong charge"
00327             if(HasPositiveCharge(&(*electrons)[selElectron1])){ // both leps positive               
00328               idcs.push_back(selElectron1);       
00329               LV_l1.SetXYZT((*electrons)[selElectron1].px(), 
00330                             (*electrons)[selElectron1].py(), 
00331                             (*electrons)[selElectron1].pz(), 
00332                             (*electrons)[selElectron1].energy());         
00333               xconstraint += (*electrons)[selElectron1].px();
00334               yconstraint += (*electrons)[selElectron1].py();
00335               
00336               idcs.push_back(-1);
00337     
00338               idcs.push_back(selMuon1);   
00339               LV_l2.SetXYZT((*muons)[selMuon1].px(), 
00340                             (*muons)[selMuon1].py(), 
00341                             (*muons)[selMuon1].pz(), 
00342                             (*muons)[selMuon1].energy());         
00343               xconstraint += (*muons)[selMuon1].px();
00344               yconstraint += (*muons)[selMuon1].py();
00345                   
00346               idcs.push_back(-1);           
00347             }
00348             else{ // both leps negative
00349               idcs.push_back(-1);           
00350             
00351               idcs.push_back(selElectron1);       
00352               LV_l2.SetXYZT((*electrons)[selElectron1].px(), 
00353                             (*electrons)[selElectron1].py(), 
00354                             (*electrons)[selElectron1].pz(), 
00355                             (*electrons)[selElectron1].energy());         
00356               xconstraint += (*electrons)[selElectron1].px();
00357               yconstraint += (*electrons)[selElectron1].py();
00358               
00359               idcs.push_back(-1);
00360     
00361               idcs.push_back(selMuon1);   
00362               LV_l1.SetXYZT((*muons)[selMuon1].px(), 
00363                             (*muons)[selMuon1].py(), 
00364                             (*muons)[selMuon1].pz(), 
00365                             (*muons)[selMuon1].energy());         
00366               xconstraint += (*muons)[selMuon1].px();
00367               yconstraint += (*muons)[selMuon1].py();                       
00368             }
00369           }       
00370         }
00371                         
00372         else if (mumu) {
00373           idcs.push_back(-1);
00374           idcs.push_back(-1);
00375         
00376           idcs.push_back(selMuon1);       
00377           LV_l1.SetXYZT((*muons)[selMuon1].px(), 
00378                         (*muons)[selMuon1].py(), 
00379                         (*muons)[selMuon1].pz(), 
00380                         (*muons)[selMuon1].energy());     
00381           xconstraint += (*muons)[selMuon1].px();
00382           yconstraint += (*muons)[selMuon1].py();       
00383         
00384           idcs.push_back(selMuon2);       
00385           LV_l2.SetXYZT((*muons)[selMuon2].px(), 
00386                         (*muons)[selMuon2].py(), 
00387                         (*muons)[selMuon2].pz(), 
00388                         (*muons)[selMuon2].energy());     
00389           xconstraint += (*muons)[selMuon2].px();
00390           yconstraint += (*muons)[selMuon2].py();
00391         }
00392                         
00393         xconstraint += (*jets)[ib].px() + (*jets)[ibbar].px() + (*mets)[0].px();
00394         yconstraint += (*jets)[ib].py() + (*jets)[ibbar].py() + (*mets)[0].py();
00395                          
00396         // calculate neutrino momenta and eventweight
00397         solver->SetConstraints(xconstraint, yconstraint);
00398         TtFullLepKinSolver::NeutrinoSolution nuSol= solver->getNuSolution( LV_l1, LV_l2 , LV_b, LV_bbar);
00399                 
00400         // add solution to the vectors of solutions if solution exists 
00401         if(nuSol.weight>0){
00402           // add the leptons and jets indices to the vector of combinations
00403           idcsV.push_back(idcs);
00404                 
00405           // add the neutrinos
00406           nusV.push_back(nuSol.neutrino);       
00407           nuBarsV.push_back(nuSol.neutrinoBar);
00408         
00409           // add the solution weight
00410           weightsV.push_back(std::make_pair(nuSol.weight, nSol));
00411           
00412           nSol++;
00413         }
00414       }
00415     }           
00416   }
00417   
00418   if(weightsV.size()==0){      
00419     //create dmummy vector 
00420     std::vector<int> idcs;
00421     for(int i=0; i<6; ++i)
00422       idcs.push_back(-1);
00423 
00424     idcsV.push_back(idcs);
00425     weightsV.push_back(std::make_pair(-1,0));
00426     reco::LeafCandidate nu;
00427     nusV.push_back(nu);
00428     reco::LeafCandidate nuBar;
00429     nuBarsV.push_back(nuBar);
00430   }
00431 
00432   // check if all vectors have correct length
00433   int weightL = weightsV.size();
00434   int nuL     = nusV.size();  
00435   int nuBarL  = nuBarsV.size();  
00436   int idxL    = idcsV.size();   
00437       
00438   if(weightL!=nuL || weightL!=nuBarL || weightL!=idxL){
00439     edm::LogWarning("TtFullLepKinSolutionProducer") << "Output vectors are of different length:"
00440     << "\n weight: " << weightL    
00441     << "\n     nu: " << nuL
00442     << "\n  nubar: " << nuBarL
00443     << "\n   idcs: " << idxL;
00444   } 
00445     
00446   // sort vectors by weight in decreasing order
00447   if(weightsV.size()>1){
00448     sort(weightsV.begin(), weightsV.end(), Compare());
00449   }
00450   
00451   // determine the number of solutions which is written in the event
00452   int stop=weightL;
00453   if(maxNComb_>0 && maxNComb_<stop) stop=maxNComb_;
00454     
00455   for(int i=0; i<stop; ++i){
00456     pWeight->push_back(weightsV[i].first);
00457     pNus   ->push_back(nusV[weightsV[i].second]);
00458     pNuBars->push_back(nuBarsV[weightsV[i].second]);    
00459     pIdcs  ->push_back(idcsV[weightsV[i].second]);    
00460   }
00461            
00462   // put the results in the event
00463   evt.put(pIdcs);     
00464   evt.put(pNus,         "fullLepNeutrinos");  
00465   evt.put(pNuBars,      "fullLepNeutrinoBars");             
00466   evt.put(pWeight,      "solWeight");  
00467   evt.put(pWrongCharge, "isWrongCharge"); 
00468 }
00469 
00470 #endif