CMS 3D CMS Logo

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