CMS 3D CMS Logo

BoostedTopProducer.cc
Go to the documentation of this file.
1 #include "BoostedTopProducer.h"
3 
4 #include <string>
5 #include <sstream>
6 #include <iostream>
7 
8 using std::string;
9 using std::cout;
10 using std::endl;
11 
12 //
13 // constants, enums and typedefs
14 //
15 
16 //
17 // static data member definitions
18 //
19 
20 //
21 // constructors and destructor
22 //
24  eleToken_ (consumes<std::vector<pat::Electron> >(iConfig.getParameter<edm::InputTag> ("electronLabel"))),
25  muoToken_ (consumes<std::vector<pat::Muon> >(iConfig.getParameter<edm::InputTag> ("muonLabel"))),
26  jetToken_ (consumes<std::vector<pat::Jet> >(iConfig.getParameter<edm::InputTag> ("jetLabel"))),
27  metToken_ (consumes<std::vector<pat::MET> >(iConfig.getParameter<edm::InputTag> ("metLabel"))),
28  solToken_ (mayConsume<TtSemiLeptonicEvent>(iConfig.getParameter<edm::InputTag> ("solLabel"))),
29  caloIsoCut_ (iConfig.getParameter<double> ("caloIsoCut") ),
30  mTop_ (iConfig.getParameter<double> ("mTop") )
31 {
32  //register products
33  produces<std::vector<reco::CompositeCandidate> > ();
34 }
35 
36 
38 {
39 }
40 
41 
42 //
43 // member functions
44 //
45 
46 // ------------ method called to produce the data ------------
47 void
49 {
50 
51  using namespace edm;
52 
53  bool debug = false;
54 
55  // -----------------------------------------------------
56  // get the bare PAT objects
57  // -----------------------------------------------------
59  iEvent.getByToken(muoToken_,muonHandle);
60  std::vector<pat::Muon> const & muons = *muonHandle;
61 
63  iEvent.getByToken(jetToken_,jetHandle);
64  std::vector<pat::Jet> const & jets = *jetHandle;
65 
67  iEvent.getByToken(eleToken_,electronHandle);
68  std::vector<pat::Electron> const & electrons = *electronHandle;
69 
71  iEvent.getByToken(metToken_,metHandle);
72  std::vector<pat::MET> const & mets = *metHandle;
73 
74  // -----------------------------------------------------
75  // Event Preselection:
76  // <= 1 isolated electron or muon
77  // >= 1 electron or muon
78  // >= 2 jets
79  // >= 1 missing et
80  //
81  // To explain:
82  // We want to look at leptons within "top jets" in some
83  // cases. This means the isolation will kill those events.
84  // However, if there IS an isolated lepton, we want only
85  // one of them.
86  //
87  // So to select the prompt W lepton, the logic is:
88  // 1. If there is an isolated lepton, accept it as the W lepton.
89  // 2. Else, take the highest Pt lepton (possibly non-isolated)
90  //
91  // -----------------------------------------------------
92  bool preselection = true;
93 
94  // This will hold the prompt W lepton candidate, and a
95  // maximum pt decision variable
96  double maxWLeptonPt = -1;
97  //reco::Candidate const * Wlepton = 0;
98 
99  // ----------------------
100  // Find isolated muons, and highest pt lepton
101  // ----------------------
102  std::vector<pat::Muon>::const_iterator isolatedMuon = muons.end();
103  std::vector<pat::Muon>::const_iterator muon = muons.end();
104  unsigned int nIsolatedMuons = 0;
105  std::vector<pat::Muon>::const_iterator muonIt = muons.begin(),
106  muonEnd = muons.end();
107  for (; muonIt != muonEnd; ++muonIt ) {
108 
109  // Find highest pt lepton
110  double pt = muonIt->pt();
111  if ( pt > maxWLeptonPt ) {
112  maxWLeptonPt = pt;
113  muon = muonIt;
114  }
115 
116  // Find any isolated muons
117  double caloIso = muonIt->caloIso();
118  if ( caloIso >= 0 && caloIso < caloIsoCut_ ) {
119  nIsolatedMuons++;
120  isolatedMuon = muonIt;
121  }
122  }
123 
124  // ----------------------
125  // Find isolated electrons, and highest pt lepton
126  // ----------------------
127  std::vector<pat::Electron>::const_iterator isolatedElectron = electrons.end();
128  std::vector<pat::Electron>::const_iterator electron = electrons.end();
129  unsigned int nIsolatedElectrons = 0;
130  std::vector<pat::Electron>::const_iterator electronIt = electrons.begin(),
131  electronEnd = electrons.end();
132  for (; electronIt != electronEnd; ++electronIt ) {
133 
134  // Find highest pt lepton
135  double pt = electronIt->pt();
136  if ( pt > maxWLeptonPt ) {
137  maxWLeptonPt = pt;
138  electron = electronIt;
139  }
140 
141  // Find any isolated electrons
142  double caloIso = electronIt->caloIso();
143  if ( caloIso >= 0 && caloIso < caloIsoCut_ ) {
144  nIsolatedElectrons++;
145  isolatedElectron = electronIt;
146  }
147  }
148 
149 
150  // ----------------------
151  // Now decide on the "prompt" lepton from the W:
152  // Choose isolated leptons over all, and if no isolated,
153  // then take highest pt lepton.
154  // ----------------------
155  bool isMuon = true;
156  if ( isolatedMuon != muonEnd ) { muon = isolatedMuon; isMuon = true; }
157  else if ( isolatedElectron != electronEnd ) { electron = isolatedElectron; isMuon = false; }
158  else {
159  // Set to the highest pt lepton
160  if ( muon != muonEnd && electron == electronEnd ) isMuon = true;
161  else if ( muon == muonEnd && electron != electronEnd ) isMuon = false;
162  else if ( muon != muonEnd && electron != electronEnd ) {
163  isMuon = muon->pt() > electron->pt();
164  }
165  }
166 
167  // ----------------------
168  // Veto events that have more than one isolated lepton
169  // ----------------------
170  int nIsolatedLeptons = nIsolatedMuons + nIsolatedElectrons;
171  if ( nIsolatedLeptons > 1 ) {
172  preselection = false;
173  }
174 
175  // ----------------------
176  // Veto events that have no prompt lepton candidates
177  // ----------------------
178  if ( muon == muonEnd && electron == electronEnd ) {
179  preselection = false;
180  }
181 
182  // ----------------------
183  // Veto events with < 2 jets or no missing et
184  // ----------------------
185  if ( jets.size() < 2 ||
186  mets.empty() ) {
187  preselection = false;
188  }
189 
190  bool write = false;
191 
192 
193 
194  // -----------------------------------------------------
195  //
196  // CompositeCandidates to store the event solution.
197  // This will take one of two forms:
198  // a) lv jj jj Full reconstruction.
199  //
200  // ttbar->
201  // (hadt -> (hadW -> hadp + hadq) + hadb) +
202  // (lept -> (lepW -> lepton + neutrino) + lepb)
203  //
204  // b) lv jj (j) Partial reconstruction, associate
205  // at least 1 jet to the lepton
206  // hemisphere, and at least one jet in
207  // the opposite hemisphere.
208  //
209  // ttbar->
210  // (hadt -> (hadJet1 [+ hadJet2] ) ) +
211  // (lept -> (lepW -> lepton + neutrino) + lepJet1 )
212  //
213  // There will also be two subcategories of (b) that
214  // will correspond to physics cases:
215  //
216  // b1) Lepton is isolated: Moderate ttbar mass.
217  // b2) Lepton is nonisolated: High ttbar mass.
218  //
219  // -----------------------------------------------------
220  reco::CompositeCandidate ttbar("ttbar");
221  AddFourMomenta addFourMomenta;
222 
223 
224  // Main decisions after preselection
225  if ( preselection ) {
226 
227  if ( debug ) cout << "Preselection is satisfied" << endl;
228 
229  if ( debug ) cout << "Jets.size() = " << jets.size() << endl;
230 
231  // This will be modified for the z solution, so make a copy
232  pat::MET neutrino( mets[0] );
233 
234 
235  // 1. First examine the low mass case with 4 jets and widely separated
236  // products. We take out the TtSemiLeptonicEvent from the TQAF and
237  // form the ttbar invariant mass.
238  if ( jets.size() >= 4 ) {
239 
240  if ( debug ) cout << "Getting ttbar semileptonic solution" << endl;
241 
242  // get the ttbar semileptonic event solution if there are more than 3 jets
244  iEvent.getByToken(solToken_, eSol);
245 
246  // Have solution, continue
247  if ( eSol.isValid() ) {
248  if ( debug ) cout << "Got a nonzero size solution vector" << endl;
249  // Just set the ttbar solution to the best ttbar solution from
250  // TtSemiEvtSolutionMaker
252  write = true;
253  }
254  // No ttbar solution with 4 jets, something is weird, print a warning
255  else {
256  edm::LogWarning("DataNotFound") << "BoostedTopProducer: Cannot find TtSemiEvtSolution\n";
257  }
258  }
259  // 2. With 2 or 3 jets, we decide based on the separation between
260  // the lepton and the closest jet in that hemisphere whether to
261  // consider it "moderate" or "high" mass.
262  else if ( jets.size() == 2 || jets.size() == 3 ) {
263 
264  // ------------------------------------------------------------------
265  // First create a leptonic W candidate
266  // ------------------------------------------------------------------
267  reco::CompositeCandidate lepW("lepW");
268 
269  if ( isMuon ) {
270  if ( debug ) cout << "Adding muon as daughter" << endl;
271  lepW.addDaughter( *muon, "muon" );
272  } else {
273  if ( debug ) cout << "Adding electron as daughter" << endl;
274  lepW.addDaughter( *electron, "electron" );
275  }
276  if ( debug ) cout << "Adding neutrino as daughter" << endl;
277  lepW.addDaughter ( neutrino, "neutrino");
278  addFourMomenta.set( lepW );
279 
280  //bool nuzHasComplex = false;
281  METzCalculator zcalculator;
282 
283  zcalculator.SetMET( neutrino );
284  if ( isMuon )
285  zcalculator.SetMuon( *muon );
286  else
287  zcalculator.SetMuon( *electron ); // This name is misleading, should be setLepton
288  double neutrinoPz = zcalculator.Calculate(1);// closest to the lepton Pz
289  //if (zcalculator.IsComplex()) nuzHasComplex = true;
290  // Set the neutrino pz
291  neutrino.setPz( neutrinoPz );
292 
293  if ( debug ) cout << "Set neutrino pz to " << neutrinoPz << endl;
294 
295  // ------------------------------------------------------------------
296  // Next ensure that there is a jet within the hemisphere of the
297  // leptonic W, and one in the opposite hemisphere
298  // ------------------------------------------------------------------
299  reco::CompositeCandidate hadt("hadt");
300  reco::CompositeCandidate lept("lept");
301  if ( debug ) cout << "Adding lepW as daughter" << endl;
302  lept.addDaughter( lepW, "lepW" );
303 
304  std::string hadName("hadJet");
305  std::string lepName("lepJet");
306 
307  // Get the W momentum
308  TLorentzVector p4_W (lepW.px(), lepW.py(), lepW.pz(), lepW.energy() );
309 
310  // Loop over the jets
311  std::vector<pat::Jet>::const_iterator jetit = jets.begin(),
312  jetend = jets.end();
313  unsigned long ii = 1; // Count by 1 for naming histograms
314  for ( ; jetit != jetend; ++jetit, ++ii ) {
315  // Get this jet's momentum
316  TLorentzVector p4_jet (jetit->px(), jetit->py(), jetit->pz(), jetit->energy() );
317 
318  // Calculate psi (like DeltaR, only more invariant under Rapidity)
319  double psi = Psi( p4_W, p4_jet, mTop_ );
320 
321  // Get jets that are in the leptonic hemisphere
322  if ( psi < TMath::Pi() ) {
323  // Add this jet to the leptonic top
324  std::stringstream s;
325  s << lepName << ii;
326  if ( debug ) cout << "Adding daughter " << s.str() << endl;
327  lept.addDaughter( *jetit, s.str() );
328  }
329  // Get jets that are in the hadronic hemisphere
330  if ( psi > TMath::Pi() ) {
331  // Add this jet to the hadronic top. We don't
332  // make any W hypotheses in this case, since
333  // we cannot determine which of the three
334  // jets are merged.
335  std::stringstream s;
336  s << hadName << ii;
337  if ( debug ) cout << "Adding daughter " << s.str() << endl;
338  hadt.addDaughter( *jetit, s.str() );
339 
340  }
341  } // end loop over jets
342 
343  addFourMomenta.set( lept );
344  addFourMomenta.set( hadt );
345 
346  bool lepWHasJet = lept.numberOfDaughters() >= 2; // W and >= 1 jet
347  bool hadWHasJet = hadt.numberOfDaughters() >= 1; // >= 1 jet
348  if ( lepWHasJet && hadWHasJet ) {
349  if ( debug ) cout << "Adding daughters lept and hadt" << endl;
350  ttbar.addDaughter( lept, "lept");
351  ttbar.addDaughter( hadt, "hadt");
352  addFourMomenta.set( ttbar );
353  write = true;
354  } // end of hadronic jet and leptonic jet
355 
356 
357  } // end if there are 2 or 3 jets
358 
359  } // end if preselection is satisfied
360 
361  // Write the solution to the event record
362  std::vector<reco::CompositeCandidate> ttbarList;
363  if ( write ) {
364  if ( debug ) cout << "Writing out" << endl;
365  ttbarList.push_back( ttbar );
366  }
367  std::unique_ptr<std::vector<reco::CompositeCandidate> > pTtbar ( new std::vector<reco::CompositeCandidate>(ttbarList) );
368  iEvent.put(std::move(pTtbar));
369 
370 
371 }
372 
373 double
374 BoostedTopProducer::Psi(const TLorentzVector& p1, const TLorentzVector& p2, double mass) {
375 
376  TLorentzVector ptot = p1 + p2;
377  Double_t theta1 = TMath::ACos( (p1.Vect().Dot(ptot.Vect()))/(p1.P()*ptot.P()) );
378  Double_t theta2 = TMath::ACos( (p2.Vect().Dot(ptot.Vect()))/(p2.P()*ptot.P()) );
379  //Double_t sign = 1.;
380  //if ( (theta1+theta2) > (TMath::Pi()/2) ) sign = -1.;
381  double th1th2 = theta1 + theta2;
382  double psi = (p1.P()+p2.P())*TMath::Abs(TMath::Sin(th1th2))/(2.* mass );
383  if ( th1th2 > (TMath::Pi()/2) )
384  psi = (p1.P()+p2.P())*( 1. + TMath::Abs(TMath::Cos(th1th2)))/(2.* mass );
385 
386  return psi;
387 }
388 
389 //define this as a plug-in
const double Pi
Analysis-level MET class.
Definition: MET.h:43
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:125
bool isMuon(const Candidate &part)
Definition: pdgIdUtils.h:11
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
edm::EDGetTokenT< std::vector< pat::Electron > > eleToken_
edm::EDGetTokenT< std::vector< pat::Muon > > muoToken_
double px() const final
x coordinate of momentum vector
edm::EDGetTokenT< TtSemiLeptonicEvent > solToken_
void produce(edm::Event &, const edm::EventSetup &) override
Class derived from the TtEvent for the semileptonic decay channel.
std::map< std::string, int, std::less< std::string > > psi
edm::EDGetTokenT< std::vector< pat::Jet > > jetToken_
void SetMET(const pat::MET &MET)
Set MET.
Definition: HeavyIon.h:7
edm::EDGetTokenT< std::vector< pat::MET > > metToken_
int iEvent
Definition: GenABIO.cc:224
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
Definition: Muon.py:1
Definition: Jet.py:1
double pz() const final
z coordinate of momentum vector
vector< PseudoJet > jets
T Abs(T a)
Definition: MathUtil.h:49
void SetMuon(const pat::Particle &lepton)
Set Muon.
double energy() const final
energy
BoostedTopProducer(const edm::ParameterSet &)
bool isValid() const
Definition: HandleBase.h:74
double p2[4]
Definition: TauolaWrapper.h:90
void addDaughter(const Candidate &, const std::string &s="")
add a clone of the passed candidate as daughter
ii
Definition: cuy.py:590
const reco::CompositeCandidate & eventHypo(const HypoClassKey &key, const unsigned &cmb=0) const
Definition: TtEvent.h:51
#define debug
Definition: HDRShower.cc:19
double Calculate(int type=0)
member functions
double py() const final
y coordinate of momentum vector
double Psi(const TLorentzVector &p1, const TLorentzVector &p2, double mass)
~BoostedTopProducer() override
HLT enums.
double p1[4]
Definition: TauolaWrapper.h:89
void set(reco::Candidate &c) const
set up a candidate
size_type numberOfDaughters() const override
number of daughters
def write(self, setup)
void setPz(double pz) final
def move(src, dest)
Definition: eostools.py:511