00001 #ifndef TtFullLepKinSolutionProducer_h
00002 #define TtFullLepKinSolutionProducer_h
00003
00004
00005
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
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
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
00094 produces<std::vector<std::vector<int> > > ();
00095 produces<std::vector<reco::LeafCandidate> >("fullLepNeutrinos");
00096 produces<std::vector<reco::LeafCandidate> >("fullLepNeutrinoBars");
00097 produces<std::vector<double> >("solWeight");
00098 produces<bool>("isWrongCharge");
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
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
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
00152 if(jets->size()>=2) { jetsFound = true; }
00153
00154
00155 if(mets->size()>=1) { METFound = true; }
00156
00157
00158
00159 if(muons->size() + electrons->size() >=2) {
00160
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
00215 if(int(ee)+int(emu)+int(mumu)>1) {
00216 edm::LogWarning("TtFullLepKinSolutionProducer") << "Lepton selection criteria uncorrectly defined";
00217 }
00218
00219
00220 bool correctLeptons = ((electronsFound && eeChannel_) || (muonsFound && mumuChannel_) || (electronMuonFound && emuChannel_) );
00221
00222 if(isWrongCharge) correctLeptons *= searchWrongCharge_;
00223
00224 if(correctLeptons && METFound && jetsFound) {
00225
00226
00227
00228
00229 int stop=maxNJets_;
00230 if(jets->size()<static_cast<unsigned int>(stop) || stop<0) stop=jets->size();
00231
00232
00233 int nSol=0;
00234
00235
00236 for (int ib = 0; ib<stop; ib++) {
00237
00238 for (int ibbar = 0; ibbar<stop; ibbar++) {
00239
00240 if(ib==ibbar) continue;
00241
00242 std::vector<int> idcs;
00243
00244
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{
00327 if(HasPositiveCharge(&(*electrons)[selElectron1])){
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{
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
00397 solver->SetConstraints(xconstraint, yconstraint);
00398 TtFullLepKinSolver::NeutrinoSolution nuSol= solver->getNuSolution( LV_l1, LV_l2 , LV_b, LV_bbar);
00399
00400
00401 if(nuSol.weight>0){
00402
00403 idcsV.push_back(idcs);
00404
00405
00406 nusV.push_back(nuSol.neutrino);
00407 nuBarsV.push_back(nuSol.neutrinoBar);
00408
00409
00410 weightsV.push_back(std::make_pair(nuSol.weight, nSol));
00411
00412 nSol++;
00413 }
00414 }
00415 }
00416 }
00417
00418 if(weightsV.size()==0){
00419
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
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
00447 if(weightsV.size()>1){
00448 sort(weightsV.begin(), weightsV.end(), Compare());
00449 }
00450
00451
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
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