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