CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TtFullLepKinSolutionProducer.h
Go to the documentation of this file.
1 #ifndef TtFullLepKinSolutionProducer_h
2 #define TtFullLepKinSolutionProducer_h
3 
4 //
5 //
6 #include <memory>
7 #include <string>
8 #include <vector>
9 #include "TLorentzVector.h"
18 
20 public:
23 
24  void beginJob() override;
25  void produce(edm::Event& evt, const edm::EventSetup& iSetup) override;
26  void endJob() override;
27 
28 private:
29  // next methods are avoidable but they make the code legible
30  inline bool PTComp(const reco::Candidate*, const reco::Candidate*) const;
31  inline bool LepDiffCharge(const reco::Candidate*, const reco::Candidate*) const;
32  inline bool HasPositiveCharge(const reco::Candidate*) const;
33 
34  struct Compare {
35  bool operator()(std::pair<double, int> a, std::pair<double, int> b) { return a.first > b.first; }
36  };
37 
42 
47  std::vector<double> nupars_;
48 
50 };
51 
52 inline bool TtFullLepKinSolutionProducer::PTComp(const reco::Candidate* l1, const reco::Candidate* l2) const {
53  return (l1->pt() > l2->pt());
54 }
55 
57  return (l1->charge() != l2->charge());
58 }
59 
61  return (l->charge() > 0);
62 }
63 
65  // configurables
66  jetsToken_ = consumes<std::vector<pat::Jet> >(iConfig.getParameter<edm::InputTag>("jets"));
67  electronsToken_ = consumes<std::vector<pat::Electron> >(iConfig.getParameter<edm::InputTag>("electrons"));
68  muonsToken_ = consumes<std::vector<pat::Muon> >(iConfig.getParameter<edm::InputTag>("muons"));
69  metsToken_ = consumes<std::vector<pat::MET> >(iConfig.getParameter<edm::InputTag>("mets"));
70  jetCorrLevel_ = iConfig.getParameter<std::string>("jetCorrectionLevel");
71  maxNJets_ = iConfig.getParameter<int>("maxNJets");
72  maxNComb_ = iConfig.getParameter<int>("maxNComb");
73  eeChannel_ = iConfig.getParameter<bool>("eeChannel");
74  emuChannel_ = iConfig.getParameter<bool>("emuChannel");
75  mumuChannel_ = iConfig.getParameter<bool>("mumuChannel");
76  searchWrongCharge_ = iConfig.getParameter<bool>("searchWrongCharge");
77  tmassbegin_ = iConfig.getParameter<double>("tmassbegin");
78  tmassend_ = iConfig.getParameter<double>("tmassend");
79  tmassstep_ = iConfig.getParameter<double>("tmassstep");
80  nupars_ = iConfig.getParameter<std::vector<double> >("neutrino_parameters");
81 
82  // define what will be produced
83  produces<std::vector<std::vector<int> > >(); // vector of the particle inices (b, bbar, e1, e2, mu1, mu2)
84  produces<std::vector<reco::LeafCandidate> >("fullLepNeutrinos");
85  produces<std::vector<reco::LeafCandidate> >("fullLepNeutrinoBars");
86  produces<std::vector<double> >("solWeight"); //weight for a specific kin solution
87  produces<bool>("isWrongCharge"); //true if leptons have the same charge
88 }
89 
91 
94 }
95 
97 
99  //create vectors fo runsorted output
100  std::vector<std::vector<int> > idcsV;
101  std::vector<reco::LeafCandidate> nusV;
102  std::vector<reco::LeafCandidate> nuBarsV;
103  std::vector<std::pair<double, int> > weightsV;
104 
105  //create pointer for products
106  std::unique_ptr<std::vector<std::vector<int> > > pIdcs(new std::vector<std::vector<int> >);
107  std::unique_ptr<std::vector<reco::LeafCandidate> > pNus(new std::vector<reco::LeafCandidate>);
108  std::unique_ptr<std::vector<reco::LeafCandidate> > pNuBars(new std::vector<reco::LeafCandidate>);
109  std::unique_ptr<std::vector<double> > pWeight(new std::vector<double>);
110  std::unique_ptr<bool> pWrongCharge(new bool);
111 
113  evt.getByToken(jetsToken_, jets);
115  evt.getByToken(electronsToken_, electrons);
117  evt.getByToken(muonsToken_, muons);
119  evt.getByToken(metsToken_, mets);
120 
121  int selMuon1 = -1, selMuon2 = -1;
122  int selElectron1 = -1, selElectron2 = -1;
123  bool ee = false;
124  bool emu = false;
125  bool mumu = false;
126  bool isWrongCharge = false;
127  bool jetsFound = false;
128  bool METFound = false;
129  bool electronsFound = false;
130  bool electronMuonFound = false;
131  bool muonsFound = false;
132 
133  //select Jets (TopJet vector is sorted on ET)
134  if (jets->size() >= 2) {
135  jetsFound = true;
136  }
137 
138  //select MET (TopMET vector is sorted on ET)
139  if (!mets->empty()) {
140  METFound = true;
141  }
142 
143  // If we have electrons and muons available,
144  // build a solutions with electrons and muons.
145  if (muons->size() + electrons->size() >= 2) {
146  // select leptons
147  if (electrons->empty())
148  mumu = true;
149  else if (muons->empty())
150  ee = true;
151  else if (electrons->size() == 1) {
152  if (muons->size() == 1)
153  emu = true;
154  else if (PTComp(&(*electrons)[0], &(*muons)[1]))
155  emu = true;
156  else
157  mumu = true;
158  } else if (electrons->size() > 1) {
159  if (PTComp(&(*electrons)[1], &(*muons)[0]))
160  ee = true;
161  else if (muons->size() == 1)
162  emu = true;
163  else if (PTComp(&(*electrons)[0], &(*muons)[1]))
164  emu = true;
165  else
166  mumu = true;
167  }
168  if (ee && eeChannel_) {
169  if (LepDiffCharge(&(*electrons)[0], &(*electrons)[1]) || searchWrongCharge_) {
170  if (HasPositiveCharge(&(*electrons)[0]) || !LepDiffCharge(&(*electrons)[0], &(*electrons)[1])) {
171  selElectron1 = 0;
172  selElectron2 = 1;
173  } else {
174  selElectron1 = 1;
175  selElectron2 = 0;
176  }
177  electronsFound = true;
178  if (!LepDiffCharge(&(*electrons)[0], &(*electrons)[1]))
179  isWrongCharge = true;
180  }
181  } else if (emu && emuChannel_) {
182  if (LepDiffCharge(&(*electrons)[0], &(*muons)[0]) || searchWrongCharge_) {
183  selElectron1 = 0;
184  selMuon1 = 0;
185  electronMuonFound = true;
186  if (!LepDiffCharge(&(*electrons)[0], &(*muons)[0]))
187  isWrongCharge = true;
188  }
189  } else if (mumu && mumuChannel_) {
190  if (LepDiffCharge(&(*muons)[0], &(*muons)[1]) || searchWrongCharge_) {
191  if (HasPositiveCharge(&(*muons)[0]) || !LepDiffCharge(&(*muons)[0], &(*muons)[1])) {
192  selMuon1 = 0;
193  selMuon2 = 1;
194  } else {
195  selMuon1 = 1;
196  selMuon2 = 0;
197  }
198  muonsFound = true;
199  if (!LepDiffCharge(&(*muons)[0], &(*muons)[1]))
200  isWrongCharge = true;
201  }
202  }
203  }
204 
205  *pWrongCharge = isWrongCharge;
206 
207  // Check that the above work makes sense
208  if (int(ee) + int(emu) + int(mumu) > 1) {
209  edm::LogWarning("TtFullLepKinSolutionProducer") << "Lepton selection criteria uncorrectly defined";
210  }
211 
212  // Check if the leptons for the required Channel are available
213  bool correctLeptons =
214  ((electronsFound && eeChannel_) || (muonsFound && mumuChannel_) || (electronMuonFound && emuChannel_));
215  // Check for equally charged leptons if for wrong charge combinations is searched
216  if (isWrongCharge) {
217  correctLeptons = correctLeptons && searchWrongCharge_;
218  }
219 
220  if (correctLeptons && METFound && jetsFound) {
221  // run over all jets if input parameter maxNJets is -1 or
222  // adapt maxNJets if number of present jets is smaller than selected
223  // number of jets
224  int stop = maxNJets_;
225  if (jets->size() < static_cast<unsigned int>(stop) || stop < 0)
226  stop = jets->size();
227 
228  // counter for number of found kinematic solutions
229  int nSol = 0;
230 
231  // consider all permutations
232  for (int ib = 0; ib < stop; ib++) {
233  // second loop of the permutations
234  for (int ibbar = 0; ibbar < stop; ibbar++) {
235  // avoid the diagonal: b and bbar must be distinct jets
236  if (ib == ibbar)
237  continue;
238 
239  std::vector<int> idcs;
240 
241  // push back the indices of the jets
242  idcs.push_back(ib);
243  idcs.push_back(ibbar);
244 
245  TLorentzVector LV_l1;
246  TLorentzVector LV_l2;
247  TLorentzVector LV_b = TLorentzVector((*jets)[ib].correctedJet(jetCorrLevel_, "bottom").px(),
248  (*jets)[ib].correctedJet(jetCorrLevel_, "bottom").py(),
249  (*jets)[ib].correctedJet(jetCorrLevel_, "bottom").pz(),
250  (*jets)[ib].correctedJet(jetCorrLevel_, "bottom").energy());
251  TLorentzVector LV_bbar = TLorentzVector((*jets)[ibbar].correctedJet(jetCorrLevel_, "bottom").px(),
252  (*jets)[ibbar].correctedJet(jetCorrLevel_, "bottom").py(),
253  (*jets)[ibbar].correctedJet(jetCorrLevel_, "bottom").pz(),
254  (*jets)[ibbar].correctedJet(jetCorrLevel_, "bottom").energy());
255 
256  double xconstraint = 0, yconstraint = 0;
257 
258  if (ee) {
259  idcs.push_back(selElectron1);
260  LV_l1.SetXYZT((*electrons)[selElectron1].px(),
261  (*electrons)[selElectron1].py(),
262  (*electrons)[selElectron1].pz(),
263  (*electrons)[selElectron1].energy());
264  xconstraint += (*electrons)[selElectron1].px();
265  yconstraint += (*electrons)[selElectron1].py();
266 
267  idcs.push_back(selElectron2);
268  LV_l2.SetXYZT((*electrons)[selElectron2].px(),
269  (*electrons)[selElectron2].py(),
270  (*electrons)[selElectron2].pz(),
271  (*electrons)[selElectron2].energy());
272  xconstraint += (*electrons)[selElectron2].px();
273  yconstraint += (*electrons)[selElectron2].py();
274 
275  idcs.push_back(-1);
276  idcs.push_back(-1);
277  }
278 
279  else if (emu) {
280  if (!isWrongCharge) {
281  if (HasPositiveCharge(&(*electrons)[selElectron1])) {
282  idcs.push_back(selElectron1);
283  LV_l1.SetXYZT((*electrons)[selElectron1].px(),
284  (*electrons)[selElectron1].py(),
285  (*electrons)[selElectron1].pz(),
286  (*electrons)[selElectron1].energy());
287  xconstraint += (*electrons)[selElectron1].px();
288  yconstraint += (*electrons)[selElectron1].py();
289 
290  idcs.push_back(-1);
291  idcs.push_back(-1);
292 
293  idcs.push_back(selMuon1);
294  LV_l2.SetXYZT((*muons)[selMuon1].px(),
295  (*muons)[selMuon1].py(),
296  (*muons)[selMuon1].pz(),
297  (*muons)[selMuon1].energy());
298  xconstraint += (*muons)[selMuon1].px();
299  yconstraint += (*muons)[selMuon1].py();
300  } else {
301  idcs.push_back(-1);
302 
303  idcs.push_back(selMuon1);
304  LV_l1.SetXYZT((*muons)[selMuon1].px(),
305  (*muons)[selMuon1].py(),
306  (*muons)[selMuon1].pz(),
307  (*muons)[selMuon1].energy());
308  xconstraint += (*muons)[selMuon1].px();
309  yconstraint += (*muons)[selMuon1].py();
310 
311  idcs.push_back(selElectron1);
312  LV_l2.SetXYZT((*electrons)[selElectron1].px(),
313  (*electrons)[selElectron1].py(),
314  (*electrons)[selElectron1].pz(),
315  (*electrons)[selElectron1].energy());
316  xconstraint += (*electrons)[selElectron1].px();
317  yconstraint += (*electrons)[selElectron1].py();
318 
319  idcs.push_back(-1);
320  }
321  } else { // means "if wrong charge"
322  if (HasPositiveCharge(&(*electrons)[selElectron1])) { // both leps positive
323  idcs.push_back(selElectron1);
324  LV_l1.SetXYZT((*electrons)[selElectron1].px(),
325  (*electrons)[selElectron1].py(),
326  (*electrons)[selElectron1].pz(),
327  (*electrons)[selElectron1].energy());
328  xconstraint += (*electrons)[selElectron1].px();
329  yconstraint += (*electrons)[selElectron1].py();
330 
331  idcs.push_back(-1);
332 
333  idcs.push_back(selMuon1);
334  LV_l2.SetXYZT((*muons)[selMuon1].px(),
335  (*muons)[selMuon1].py(),
336  (*muons)[selMuon1].pz(),
337  (*muons)[selMuon1].energy());
338  xconstraint += (*muons)[selMuon1].px();
339  yconstraint += (*muons)[selMuon1].py();
340 
341  idcs.push_back(-1);
342  } else { // both leps negative
343  idcs.push_back(-1);
344 
345  idcs.push_back(selElectron1);
346  LV_l2.SetXYZT((*electrons)[selElectron1].px(),
347  (*electrons)[selElectron1].py(),
348  (*electrons)[selElectron1].pz(),
349  (*electrons)[selElectron1].energy());
350  xconstraint += (*electrons)[selElectron1].px();
351  yconstraint += (*electrons)[selElectron1].py();
352 
353  idcs.push_back(-1);
354 
355  idcs.push_back(selMuon1);
356  LV_l1.SetXYZT((*muons)[selMuon1].px(),
357  (*muons)[selMuon1].py(),
358  (*muons)[selMuon1].pz(),
359  (*muons)[selMuon1].energy());
360  xconstraint += (*muons)[selMuon1].px();
361  yconstraint += (*muons)[selMuon1].py();
362  }
363  }
364  }
365 
366  else if (mumu) {
367  idcs.push_back(-1);
368  idcs.push_back(-1);
369 
370  idcs.push_back(selMuon1);
371  LV_l1.SetXYZT(
372  (*muons)[selMuon1].px(), (*muons)[selMuon1].py(), (*muons)[selMuon1].pz(), (*muons)[selMuon1].energy());
373  xconstraint += (*muons)[selMuon1].px();
374  yconstraint += (*muons)[selMuon1].py();
375 
376  idcs.push_back(selMuon2);
377  LV_l2.SetXYZT(
378  (*muons)[selMuon2].px(), (*muons)[selMuon2].py(), (*muons)[selMuon2].pz(), (*muons)[selMuon2].energy());
379  xconstraint += (*muons)[selMuon2].px();
380  yconstraint += (*muons)[selMuon2].py();
381  }
382 
383  xconstraint += (*jets)[ib].px() + (*jets)[ibbar].px() + (*mets)[0].px();
384  yconstraint += (*jets)[ib].py() + (*jets)[ibbar].py() + (*mets)[0].py();
385 
386  // calculate neutrino momenta and eventweight
387  solver->SetConstraints(xconstraint, yconstraint);
388  TtFullLepKinSolver::NeutrinoSolution nuSol = solver->getNuSolution(LV_l1, LV_l2, LV_b, LV_bbar);
389 
390  // add solution to the vectors of solutions if solution exists
391  if (nuSol.weight > 0) {
392  // add the leptons and jets indices to the vector of combinations
393  idcsV.push_back(idcs);
394 
395  // add the neutrinos
396  nusV.push_back(nuSol.neutrino);
397  nuBarsV.push_back(nuSol.neutrinoBar);
398 
399  // add the solution weight
400  weightsV.push_back(std::make_pair(nuSol.weight, nSol));
401 
402  nSol++;
403  }
404  }
405  }
406  }
407 
408  if (weightsV.empty()) {
409  //create dmummy vector
410  std::vector<int> idcs;
411  idcs.reserve(6);
412  for (int i = 0; i < 6; ++i)
413  idcs.push_back(-1);
414 
415  idcsV.push_back(idcs);
416  weightsV.push_back(std::make_pair(-1, 0));
418  nusV.push_back(nu);
419  reco::LeafCandidate nuBar;
420  nuBarsV.push_back(nuBar);
421  }
422 
423  // check if all vectors have correct length
424  int weightL = weightsV.size();
425  int nuL = nusV.size();
426  int nuBarL = nuBarsV.size();
427  int idxL = idcsV.size();
428 
429  if (weightL != nuL || weightL != nuBarL || weightL != idxL) {
430  edm::LogWarning("TtFullLepKinSolutionProducer")
431  << "Output vectors are of different length:"
432  << "\n weight: " << weightL << "\n nu: " << nuL << "\n nubar: " << nuBarL << "\n idcs: " << idxL;
433  }
434 
435  // sort vectors by weight in decreasing order
436  if (weightsV.size() > 1) {
437  sort(weightsV.begin(), weightsV.end(), Compare());
438  }
439 
440  // determine the number of solutions which is written in the event
441  int stop = weightL;
442  if (maxNComb_ > 0 && maxNComb_ < stop)
443  stop = maxNComb_;
444 
445  for (int i = 0; i < stop; ++i) {
446  pWeight->push_back(weightsV[i].first);
447  pNus->push_back(nusV[weightsV[i].second]);
448  pNuBars->push_back(nuBarsV[weightsV[i].second]);
449  pIdcs->push_back(idcsV[weightsV[i].second]);
450  }
451 
452  // put the results in the event
453  evt.put(std::move(pIdcs));
454  evt.put(std::move(pNus), "fullLepNeutrinos");
455  evt.put(std::move(pNuBars), "fullLepNeutrinoBars");
456  evt.put(std::move(pWeight), "solWeight");
457  evt.put(std::move(pWrongCharge), "isWrongCharge");
458 }
459 
460 #endif
bool operator()(std::pair< double, int > a, std::pair< double, int > b)
edm::EDGetTokenT< std::vector< pat::Muon > > muonsToken_
bool LepDiffCharge(const reco::Candidate *, const reco::Candidate *) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:133
NeutrinoSolution getNuSolution(const TLorentzVector &LV_l, const TLorentzVector &LV_l_, const TLorentzVector &LV_b, const TLorentzVector &LV_b_)
int ib
Definition: cuy.py:661
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:539
virtual double pt() const =0
transverse momentum
bool HasPositiveCharge(const reco::Candidate *) const
void SetConstraints(const double xx=0, const double yy=0)
U second(std::pair< T, U > const &p)
void produce(edm::Event &evt, const edm::EventSetup &iSetup) override
bool PTComp(const reco::Candidate *, const reco::Candidate *) const
vector< PseudoJet > jets
def move
Definition: eostools.py:511
virtual int charge() const =0
electric charge
edm::EDGetTokenT< std::vector< pat::MET > > metsToken_
edm::EDGetTokenT< std::vector< pat::Jet > > jetsToken_
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
double b
Definition: hdecay.h:118
TtFullLepKinSolutionProducer(const edm::ParameterSet &iConfig)
edm::EDGetTokenT< std::vector< pat::Electron > > electronsToken_
tuple muons
Definition: patZpeak.py:39
double a
Definition: hdecay.h:119
Log< level::Warning, false > LogWarning