CMS 3D CMS Logo

TtDilepEvtSolutionMaker.cc
Go to the documentation of this file.
4 
10 
13 
14 #include <memory>
15 #include <string>
16 #include <vector>
17 
19 public:
20  explicit TtDilepEvtSolutionMaker(const edm::ParameterSet& iConfig);
21  ~TtDilepEvtSolutionMaker() override;
22 
23  void beginJob() override;
24  void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
25 
26 private:
27  // next methods are avoidable but they make the code legible
28  inline bool PTComp(const reco::Candidate*, const reco::Candidate*) const;
29  inline bool LepDiffCharge(const reco::Candidate*, const reco::Candidate*) const;
30  inline bool HasPositiveCharge(const reco::Candidate*) const;
31 
32 private:
40  unsigned int nrCombJets_;
44  std::vector<double> nupars_;
45 
48 };
49 
50 inline bool TtDilepEvtSolutionMaker::PTComp(const reco::Candidate* l1, const reco::Candidate* l2) const {
51  return (l1->pt() > l2->pt());
52 }
53 
55  return (l1->charge() != l2->charge());
56 }
57 
58 inline bool TtDilepEvtSolutionMaker::HasPositiveCharge(const reco::Candidate* l) const { return (l->charge() > 0); }
59 
61  // configurables
62  electronSourceToken_ = consumes<std::vector<pat::Electron> >(iConfig.getParameter<edm::InputTag>("electronSource"));
63  muonSourceToken_ = consumes<std::vector<pat::Muon> >(iConfig.getParameter<edm::InputTag>("muonSource"));
64  tauSourceToken_ = consumes<std::vector<pat::Tau> >(iConfig.getParameter<edm::InputTag>("tauSource"));
65  metSourceToken_ = consumes<std::vector<pat::MET> >(iConfig.getParameter<edm::InputTag>("metSource"));
66  jetSourceToken_ = consumes<std::vector<pat::Jet> >(iConfig.getParameter<edm::InputTag>("jetSource"));
67  jetCorrScheme_ = iConfig.getParameter<int>("jetCorrectionScheme");
68  evtSourceToken_ = mayConsume<TtGenEvent>(iConfig.getParameter<edm::InputTag>("evtSource"));
69  nrCombJets_ = iConfig.getParameter<unsigned int>("nrCombJets");
70  matchToGenEvt_ = iConfig.getParameter<bool>("matchToGenEvt");
71  calcTopMass_ = iConfig.getParameter<bool>("calcTopMass");
72  useMCforBest_ = iConfig.getParameter<bool>("bestSolFromMC");
73  eeChannel_ = iConfig.getParameter<bool>("eeChannel");
74  emuChannel_ = iConfig.getParameter<bool>("emuChannel");
75  mumuChannel_ = iConfig.getParameter<bool>("mumuChannel");
76  mutauChannel_ = iConfig.getParameter<bool>("mutauChannel");
77  etauChannel_ = iConfig.getParameter<bool>("etauChannel");
78  tautauChannel_ = iConfig.getParameter<bool>("tautauChannel");
79  tmassbegin_ = iConfig.getParameter<double>("tmassbegin");
80  tmassend_ = iConfig.getParameter<double>("tmassend");
81  tmassstep_ = iConfig.getParameter<double>("tmassstep");
82  nupars_ = iConfig.getParameter<std::vector<double> >("neutrino_parameters");
83 
84  // define what will be produced
85  produces<std::vector<TtDilepEvtSolution> >();
86 
88 }
89 
91 
94 }
95 
98  iEvent.getByToken(tauSourceToken_, taus);
100  iEvent.getByToken(muonSourceToken_, muons);
104  iEvent.getByToken(metSourceToken_, mets);
106  iEvent.getByToken(jetSourceToken_, jets);
107 
108  int selMuonp = -1, selMuonm = -1;
109  int selElectronp = -1, selElectronm = -1;
110  int selTaup = -1, selTaum = -1;
111  bool leptonFound = false;
112  bool mumu = false;
113  bool emu = false;
114  bool ee = false;
115  bool etau = false;
116  bool mutau = false;
117  bool tautau = false;
118  bool leptonFoundEE = false;
119  bool leptonFoundMM = false;
120  bool leptonFoundTT = false;
121  bool leptonFoundEpMm = false;
122  bool leptonFoundEmMp = false;
123  bool leptonFoundEpTm = false;
124  bool leptonFoundEmTp = false;
125  bool leptonFoundMpTm = false;
126  bool leptonFoundMmTp = false;
127  bool jetsFound = false;
128  bool METFound = false;
129  std::vector<int> JetVetoByTaus;
130 
131  //select MET (TopMET vector is sorted on ET)
132  if (!mets->empty()) {
133  METFound = true;
134  }
135 
136  // If we have electrons and muons available,
137  // build a solutions with electrons and muons.
138  if (muons->size() + electrons->size() >= 2) {
139  // select leptons
140  if (electrons->empty())
141  mumu = true;
142  else if (muons->empty())
143  ee = true;
144  else if (electrons->size() == 1) {
145  if (muons->size() == 1)
146  emu = true;
147  else if (PTComp(&(*electrons)[0], &(*muons)[1]))
148  emu = true;
149  else
150  mumu = true;
151  } else if (electrons->size() > 1) {
152  if (PTComp(&(*electrons)[1], &(*muons)[0]))
153  ee = true;
154  else if (muons->size() == 1)
155  emu = true;
156  else if (PTComp(&(*electrons)[0], &(*muons)[1]))
157  emu = true;
158  else
159  mumu = true;
160  }
161  if (ee) {
162  if (LepDiffCharge(&(*electrons)[0], &(*electrons)[1])) {
163  leptonFound = true;
164  leptonFoundEE = true;
165  if (HasPositiveCharge(&(*electrons)[0])) {
166  selElectronp = 0;
167  selElectronm = 1;
168  } else {
169  selElectronp = 1;
170  selElectronm = 0;
171  }
172  }
173  } else if (emu) {
174  if (LepDiffCharge(&(*electrons)[0], &(*muons)[0])) {
175  leptonFound = true;
176  if (HasPositiveCharge(&(*electrons)[0])) {
177  leptonFoundEpMm = true;
178  selElectronp = 0;
179  selMuonm = 0;
180  } else {
181  leptonFoundEmMp = true;
182  selMuonp = 0;
183  selElectronm = 0;
184  }
185  }
186  } else if (mumu) {
187  if (LepDiffCharge(&(*muons)[0], &(*muons)[1])) {
188  leptonFound = true;
189  leptonFoundMM = true;
190  if (HasPositiveCharge(&(*muons)[0])) {
191  selMuonp = 0;
192  selMuonm = 1;
193  } else {
194  selMuonp = 1;
195  selMuonm = 0;
196  }
197  }
198  }
199  //select Jets (TopJet vector is sorted on ET)
200  if (jets->size() >= 2) {
201  jetsFound = true;
202  }
203  }
204  // If a tau is needed to have two leptons, then only consider the taus.
205  // This is the minimal modification of the dilept selection that includes taus,
206  // since we are considering taus only when no other solution exist.
207  else if (muons->size() + electrons->size() == 1 && !taus->empty()) {
208  // select leptons
209  if (muons->size() == 1) {
210  mutau = true;
211  // depending on the muon charge, set the right muon index and specify channel
212  int expectedCharge = -muons->begin()->charge();
213  int* tauIdx = nullptr;
214  if (expectedCharge < 0) {
215  selMuonp = 0;
216  tauIdx = &selTaum;
217  leptonFoundMpTm = true;
218  } else {
219  selMuonm = 0;
220  tauIdx = &selTaup;
221  leptonFoundMmTp = true;
222  }
223  // loop over the vector of taus to find the ones
224  // that have the charge opposite to the muon one, and do not match in eta-phi
225  std::vector<std::vector<pat::Tau>::const_iterator> subset1;
226  for (std::vector<pat::Tau>::const_iterator tau = taus->begin(); tau < taus->end(); ++tau) {
227  if (tau->charge() * expectedCharge >= 0 && DeltaR<pat::Particle>()(*tau, *(muons->begin())) > 0.1) {
228  *tauIdx = tau - taus->begin();
229  leptonFound = true;
230  subset1.push_back(tau);
231  }
232  }
233  // if there are more than one tau with ecalIsol==0, take the smallest E/P
234  float iso = 999.;
235  for (std::vector<std::vector<pat::Tau>::const_iterator>::const_iterator tau = subset1.begin();
236  tau < subset1.end();
237  ++tau) {
238  if ((*tau)->isPFTau() && (*tau)->isolationPFChargedHadrCandsPtSum() < iso) {
239  *tauIdx = *tau - taus->begin();
240  iso = (*tau)->isolationPFChargedHadrCandsPtSum();
241  }
242  }
243 
244  // check that one combination has been found
245  if (!leptonFound) {
246  leptonFoundMpTm = false;
247  leptonFoundMmTp = false;
248  }
249  // discard the jet that matches the tau (if one)
250  if (leptonFound) {
251  for (std::vector<pat::Jet>::const_iterator jet = jets->begin(); jet < jets->end(); ++jet) {
252  if (DeltaR<pat::Particle, pat::Jet>()(*(taus->begin() + *tauIdx), *jet) < 0.1) {
253  JetVetoByTaus.push_back(jet - jets->begin());
254  }
255  }
256  }
257  } else {
258  etau = true;
259  // depending on the electron charge, set the right electron index and specify channel
260  int expectedCharge = -electrons->begin()->charge();
261  int* tauIdx = nullptr;
262  if (expectedCharge < 0) {
263  selElectronp = 0;
264  tauIdx = &selTaum;
265  leptonFoundEpTm = true;
266  } else {
267  selElectronm = 0;
268  tauIdx = &selTaup;
269  leptonFoundEmTp = true;
270  }
271  // loop over the vector of taus to find the ones
272  // that have the charge opposite to the muon one, and do not match in eta-phi
273  std::vector<std::vector<pat::Tau>::const_iterator> subset1;
274  for (std::vector<pat::Tau>::const_iterator tau = taus->begin(); tau < taus->end(); ++tau) {
275  if (tau->charge() * expectedCharge >= 0 && DeltaR<pat::Particle>()(*tau, *(electrons->begin())) > 0.1) {
276  *tauIdx = tau - taus->begin();
277  leptonFound = true;
278  subset1.push_back(tau);
279  }
280  }
281  // if there are more than one tau with ecalIsol==0, take the smallest E/P
282  float iso = 999.;
283  for (std::vector<std::vector<pat::Tau>::const_iterator>::const_iterator tau = subset1.begin();
284  tau < subset1.end();
285  ++tau) {
286  if ((*tau)->isPFTau() && (*tau)->isolationPFChargedHadrCandsPtSum() < iso) {
287  *tauIdx = *tau - taus->begin();
288  iso = (*tau)->isolationPFChargedHadrCandsPtSum();
289  }
290  }
291 
292  // check that one combination has been found
293  if (!leptonFound) {
294  leptonFoundEpTm = false;
295  leptonFoundEmTp = false;
296  }
297  // discard the jet that matches the tau (if one)
298  if (leptonFound) {
299  for (std::vector<pat::Jet>::const_iterator jet = jets->begin(); jet < jets->end(); ++jet) {
300  if (DeltaR<pat::Particle, pat::Jet>()(*(taus->begin() + *tauIdx), *jet) < 0.1) {
301  JetVetoByTaus.push_back(jet - jets->begin());
302  }
303  }
304  }
305  }
306  // select Jets (TopJet vector is sorted on ET)
307  jetsFound = ((jets->size() - JetVetoByTaus.size()) >= 2);
308  } else if (taus->size() > 1) {
309  tautau = true;
310  if (LepDiffCharge(&(*taus)[0], &(*taus)[1])) {
311  leptonFound = true;
312  leptonFoundTT = true;
313  if (HasPositiveCharge(&(*taus)[0])) {
314  selTaup = 0;
315  selTaum = 1;
316  } else {
317  selTaup = 1;
318  selTaum = 0;
319  }
320  }
321  for (std::vector<pat::Jet>::const_iterator jet = jets->begin(); jet < jets->end(); ++jet) {
322  if (DeltaR<pat::Particle, pat::Jet>()((*taus)[0], *jet) < 0.1 ||
323  DeltaR<pat::Particle, pat::Jet>()((*taus)[1], *jet) < 0.1) {
324  JetVetoByTaus.push_back(jet - jets->begin());
325  }
326  }
327  // select Jets (TopJet vector is sorted on ET)
328  jetsFound = ((jets->size() - JetVetoByTaus.size()) >= 2);
329  }
330 
331  // Check that the above work makes sense
332  if (int(ee) + int(emu) + int(mumu) + int(etau) + int(mutau) + int(tautau) > 1)
333  std::cout << "[TtDilepEvtSolutionMaker]: "
334  << "Lepton selection criteria uncorrectly defined" << std::endl;
335 
336  bool correctLepton = (leptonFoundEE && eeChannel_) || ((leptonFoundEmMp || leptonFoundEpMm) && emuChannel_) ||
337  (leptonFoundMM && mumuChannel_) || ((leptonFoundMmTp || leptonFoundMpTm) && mutauChannel_) ||
338  ((leptonFoundEmTp || leptonFoundEpTm) && etauChannel_) || (leptonFoundTT && tautauChannel_);
339 
340  std::vector<TtDilepEvtSolution>* evtsols = new std::vector<TtDilepEvtSolution>();
341  if (correctLepton && METFound && jetsFound) {
342  // protect against reading beyond array boundaries while discounting vetoed jets
343  unsigned int nrCombJets = 0;
344  unsigned int numberOfJets = 0;
345  for (; nrCombJets < jets->size() && numberOfJets < nrCombJets_; ++nrCombJets) {
346  if (find(JetVetoByTaus.begin(), JetVetoByTaus.end(), int(nrCombJets)) == JetVetoByTaus.end())
347  ++numberOfJets;
348  }
349  // consider all permutations
350  for (unsigned int ib = 0; ib < nrCombJets; ib++) {
351  // skipped jet vetoed during components-flagging.
352  if (find(JetVetoByTaus.begin(), JetVetoByTaus.end(), int(ib)) != JetVetoByTaus.end())
353  continue;
354  // second loop of the permutations
355  for (unsigned int ibbar = 0; ibbar < nrCombJets; ibbar++) {
356  // avoid the diagonal: b and bbar must be distinct jets
357  if (ib == ibbar)
358  continue;
359  // skipped jet vetoed during components-flagging.
360  if (find(JetVetoByTaus.begin(), JetVetoByTaus.end(), int(ibbar)) != JetVetoByTaus.end())
361  continue;
362  // Build and save a solution
363  TtDilepEvtSolution asol;
365  double xconstraint = 0, yconstraint = 0;
366  // Set e+ in the event
367  if (leptonFoundEE || leptonFoundEpMm || leptonFoundEpTm) {
368  asol.setElectronp(electrons, selElectronp);
369  xconstraint += (*electrons)[selElectronp].px();
370  yconstraint += (*electrons)[selElectronp].py();
371  }
372  // Set e- in the event
373  if (leptonFoundEE || leptonFoundEmMp || leptonFoundEmTp) {
374  asol.setElectronm(electrons, selElectronm);
375  xconstraint += (*electrons)[selElectronm].px();
376  yconstraint += (*electrons)[selElectronm].py();
377  }
378  // Set mu+ in the event
379  if (leptonFoundMM || leptonFoundEmMp || leptonFoundMpTm) {
380  asol.setMuonp(muons, selMuonp);
381  xconstraint += (*muons)[selMuonp].px();
382  yconstraint += (*muons)[selMuonp].py();
383  }
384  // Set mu- in the event
385  if (leptonFoundMM || leptonFoundEpMm || leptonFoundMmTp) {
386  asol.setMuonm(muons, selMuonm);
387  xconstraint += (*muons)[selMuonm].px();
388  yconstraint += (*muons)[selMuonm].py();
389  }
390  // Set tau- in the event
391  if (leptonFoundEpTm || leptonFoundMpTm || leptonFoundTT) {
392  asol.setTaum(taus, selTaum);
393  xconstraint += (*taus)[selTaum].px();
394  yconstraint += (*taus)[selTaum].py();
395  }
396  // Set tau+ in the event
397  if (leptonFoundEmTp || leptonFoundMmTp || leptonFoundTT) {
398  asol.setTaup(taus, selTaup);
399  xconstraint += (*taus)[selTaup].px();
400  yconstraint += (*taus)[selTaup].py();
401  }
402  // Set Jets/MET in the event
403  asol.setB(jets, ib);
404  asol.setBbar(jets, ibbar);
405  asol.setMET(mets, 0);
406  xconstraint += (*jets)[ib].px() + (*jets)[ibbar].px() + (*mets)[0].px();
407  yconstraint += (*jets)[ib].py() + (*jets)[ibbar].py() + (*mets)[0].py();
408  // if asked for, match the event solutions to the gen Event
409  if (matchToGenEvt_) {
411  iEvent.getByToken(evtSourceToken_, genEvt);
412  asol.setGenEvt(genEvt);
413  }
414  // If asked, use the kin fitter to compute the top mass
415  if (calcTopMass_) {
416  solver->SetConstraints(xconstraint, yconstraint);
418  asol = solver->addKinSolInfo(&asol);
419  }
420 
421  // these lines calculate the observables to be used in the TtDilepSignalSelection LR
422  (*myLRSignalSelObservables)(asol, iEvent);
423 
424  evtsols->push_back(asol);
425  }
426  }
427  // flag the best solution (MC matching)
428  if (matchToGenEvt_) {
429  double bestSolDR = 9999.;
430  int bestSol = -1;
431  double dR = 0.;
432  for (size_t s = 0; s < evtsols->size(); s++) {
433  dR = (*evtsols)[s].getJetResidual();
434  if (dR < bestSolDR) {
435  bestSolDR = dR;
436  bestSol = s;
437  }
438  }
439  if (bestSol != -1)
440  (*evtsols)[bestSol].setBestSol(true);
441  }
442  // put the result in the event
443  std::unique_ptr<std::vector<TtDilepEvtSolution> > pOut(evtsols);
444  iEvent.put(std::move(pOut));
445  } else {
446  // no solution: put a dummy solution in the event
447  TtDilepEvtSolution asol;
448  evtsols->push_back(asol);
449  std::unique_ptr<std::vector<TtDilepEvtSolution> > pOut(evtsols);
450  iEvent.put(std::move(pOut));
451  }
452 }
453 
edm::EDGetTokenT< std::vector< pat::Jet > > jetSourceToken_
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
bool HasPositiveCharge(const reco::Candidate *) const
void setElectronm(const edm::Handle< std::vector< pat::Electron > > &elec, int i)
Definition: deltaR.h:58
void setElectronp(const edm::Handle< std::vector< pat::Electron > > &elec, int i)
virtual double pt() const =0
transverse momentum
void setB(const edm::Handle< std::vector< pat::Jet > > &jet, int i)
edm::EDGetTokenT< std::vector< pat::Muon > > muonSourceToken_
void SetConstraints(const double xx=0, const double yy=0)
bool LepDiffCharge(const reco::Candidate *, const reco::Candidate *) const
TtDilepEvtSolutionMaker(const edm::ParameterSet &iConfig)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
edm::EDGetTokenT< std::vector< pat::Tau > > tauSourceToken_
edm::EDGetTokenT< std::vector< pat::MET > > metSourceToken_
void setMuonm(const edm::Handle< std::vector< pat::Muon > > &muon, int i)
edm::EDGetTokenT< std::vector< pat::Electron > > electronSourceToken_
int iEvent
Definition: GenABIO.cc:224
TtDilepEvtSolution addKinSolInfo(TtDilepEvtSolution *asol)
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override
void setMET(const edm::Handle< std::vector< pat::MET > > &met, int i)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
virtual int charge() const =0
electric charge
void useWeightFromMC(bool useMC)
void setTaup(const edm::Handle< std::vector< pat::Tau > > &tau, int i)
void setJetCorrectionScheme(int jetCorrScheme)
edm::EDGetTokenT< TtGenEvent > evtSourceToken_
void setGenEvt(const edm::Handle< TtGenEvent > &)
void setMuonp(const edm::Handle< std::vector< pat::Muon > > &muon, int i)
std::vector< double > nupars_
bool PTComp(const reco::Candidate *, const reco::Candidate *) const
void setTaum(const edm::Handle< std::vector< pat::Tau > > &tau, int i)
def move(src, dest)
Definition: eostools.py:511
ib
Definition: cuy.py:661
TtDilepLRSignalSelObservables * myLRSignalSelObservables
void setBbar(const edm::Handle< std::vector< pat::Jet > > &jet, int i)