CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Top_Fit.cc
Go to the documentation of this file.
1 //
2 //
3 // File: src/Top_Fit.cc
4 // Purpose: Handle jet permutations.
5 // Created: Jul, 2000, sss, based on run 1 mass analysis code.
6 //
7 // XXX handle merging jets.
8 // XXX btagging for ttH.
9 //
10 // CMSSW File : src/Top_Fit.cc
11 // Original Author : Scott Stuart Snyder <snyder@bnl.gov> for D0
12 // Imported to CMSSW by Haryo Sumowidagdo <Suharyo.Sumowidagdo@cern.ch>
13 //
14 
15 
46 #include <iostream>
47 #include <algorithm>
48 #include <cmath>
49 #include <cassert>
50 
51 using std::cout;
52 using std::endl;
53 using std::abs;
54 using std::next_permutation;
55 using std::stable_sort;
56 using std::vector;
57 using std::ostream;
58 
59 
60 namespace hitfit {
61 
62 
63 //*************************************************************************
64 // Argument handling.
65 //
66 
67 
69 //
70 // Purpose: Constructor.
71 //
72 // Inputs:
73 // defs - The Defaults instance from which to initialize.
74 //
75  : _print_event_flag (defs.get_bool ("print_event_flag")),
76  _do_higgs_flag (defs.get_bool ("do_higgs_flag")),
77  _jet_mass_cut (defs.get_float ("jet_mass_cut")),
78  _mwhad_min_cut (defs.get_float ("mwhad_min_cut")),
79  _mwhad_max_cut (defs.get_float ("mwhad_max_cut")),
80  _mtdiff_max_cut (defs.get_float ("mtdiff_max_cut")),
81  _nkeep (defs.get_int ("nkeep")),
82  _solve_nu_tmass (defs.get_bool ("solve_nu_tmass")),
83  _args (defs)
84  {
85 }
86 
87 
89 //
90 // Purpose: Return the print_event_flag parameter.
91 // See the header for documentation.
92 //
93 {
94  return _print_event_flag;
95 }
96 
97 
99 //
100 // Purpose: Return the do_higgs_flag parameter.
101 // See the header for documentation.
102 //
103 {
104  return _do_higgs_flag;
105 }
106 
107 
109 //
110 // Purpose: Return the jet_mass_cut parameter.
111 // See the header for documentation.
112 //
113 {
114  return _jet_mass_cut;
115 }
116 
117 
119 //
120 // Purpose: Return the mwhad_min_cut parameter.
121 // See the header for documentation.
122 //
123 {
124  return _mwhad_min_cut;
125 }
126 
127 
129 //
130 // Purpose: Return the mwhad_max_cut parameter.
131 // See the header for documentation.
132 //
133 {
134  return _mwhad_max_cut;
135 }
136 
137 
139 //
140 // Purpose: Return the mtdiff_max_cut parameter.
141 // See the header for documentation.
142 //
143 {
144  return _mtdiff_max_cut;
145 }
146 
147 
149 //
150 // Purpose: Return the nkeep parameter.
151 // See the header for documentation.
152 //
153 {
154  return _nkeep;
155 }
156 
157 
159 //
160 // Purpose: Return the solve_nu_tmass parameter
161 // See the header for documentation.
162 //
163 {
164  return _solve_nu_tmass;
165 }
166 
167 
169 //
170 // Purpose: Return the contained subobject parameters.
171 //
172 {
173  return _args;
174 }
175 
176 
177 
178 //*************************************************************************
179 // Helper functions.
180 //
181 
182 
183 namespace {
184 
185 
200 bool test_for_bad_masses (const Lepjets_Event& ev,
201  const Top_Fit_Args& args,
202  double mwhad,
203  double umthad,
204  double umtlep)
205 //
206 // Purpose: Apply mass cuts to see if this event should be rejected
207 // without fitting.
208 //
209 // Inputs:
210 // ev - The event to test.
211 // args - Parameter setting.
212 // mwhad - The hadronic W mass.
213 // umthad - The hadronic top mass.
214 // umtlep - The leptonic top mass.
215 //
216 // Returns:
217 // True if the event should be rejected.
218 //
219 {
220 
221  // Reject the event if any jet's mass is too large.
222  if (ev.sum (lepb_label).m() > args.jet_mass_cut() ||
223  ev.sum (hadb_label).m() > args.jet_mass_cut() ||
224  ev.sum (hadw1_label).m() > args.jet_mass_cut() ||
225  ev.sum (hadw2_label).m() > args.jet_mass_cut()) {
226  return true;
227  }
228 
229  // Reject if if the hadronic W mass is outside the window.
230  if (mwhad < args.mwhad_min_cut()) {
231  return true;
232  }
233 
234  // Reject if if the hadronic W mass is outside the window.
235  if (mwhad > args.mwhad_max_cut()) {
236  return true;
237  }
238 
239  // And if the two top masses are too far apart.
240  if (abs (umthad - umtlep) > args.mtdiff_max_cut()) {
241  return true;
242  }
243 
244  // It's ok.
245  return false;
246 }
247 
248 
258 vector<int> classify_jetperm (const vector<int>& jet_types,
259  const Lepjets_Event& ev)
260 //
261 // Purpose: Classify a jet permutation, to decide on what result
262 // lists it should be put.
263 //
264 // Inputs:
265 // jet_types - Vector of jet types.
266 // ev - The original event being fit.
267 //
268 // Returns:
269 // A list_flags vector, appropriate to pass to Fit_Results::push.
270 //
271 {
272  // Start by assuming it's on all the lists.
273  // We'll clear the flags if we see that it actually doesn't
274  // belong.
275  vector<int> out (n_lists);
276  out[all_list] = 1;
277  out[noperm_list] = 1;
278  out[semicorrect_list] = 1;
279  out[limited_isr_list] = 1;
280  out[topfour_list] = 1;
281  out[btag_list] = 1;
282  out[htag_list] = 1;
283 
284  // Loop over jets.
285  assert (jet_types.size() == ev.njets());
286  for (vector<int>::size_type i=0; i < jet_types.size(); i++)
287  {
288  {
289  int t1 = jet_types[i]; // Current type of this jet.
290  int t2 = ev.jet(i).type(); // `Correct' type of this jet.
291 
292  // Consider hadw1_label and hadw2_label the same.
293  if (t1 == hadw2_label) t1 = hadw1_label;
294  if (t2 == hadw2_label) t2 = hadw1_label;
295 
296  // If they're not the same, the permutation isn't correct.
297  if (t1 != t2) out[noperm_list] = 0;
298 
299  // Test for a semicorrect permutation.
300  // Here, all hadronic-side jets are considered equivalent.
301  if (t1 == hadw1_label) t1 = hadb_label;
302  if (t2 == hadw1_label) t2 = hadb_label;
303  if (t1 != t2) out[semicorrect_list] = 0;
304  }
305 
306  if (jet_types[i] == isr_label && i <= 2)
307  out[limited_isr_list] = 0;
308 
309  if ((jet_types[i] == isr_label && i <= 3) ||
310  (jet_types[i] != isr_label && i >= 4))
311  out[topfour_list] = 0;
312 
313  if ((ev.jet(i).svx_tag() || ev.jet(i).slt_tag()) &&
314  ! (jet_types[i] == hadb_label || jet_types[i] == lepb_label))
315  out[btag_list] = 0;
316 
317  if ((ev.jet(i).svx_tag() || ev.jet(i).slt_tag()) &&
318  ! (jet_types[i] == hadb_label || jet_types[i] == lepb_label ||
319  jet_types[i] == higgs_label))
320  out[htag_list] = 0;
321  }
322  return out;
323 }
324 
325 
334 void set_jet_types (const vector<int>& jet_types,
335  Lepjets_Event& ev)
336 //
337 // Purpose: Update EV with a new set of jet types.
338 //
339 // Inputs:
340 // jet_types - Vector of new jet types.
341 // ev - The event to update.
342 //
343 // Outputs:
344 // ev - The updated event.
345 //
346 {
347  assert (ev.njets() == jet_types.size());
348  bool saw_hadw1 = false;
349  for (vector<int>::size_type i=0; i < ev.njets(); i++) {
350  int t = jet_types[i];
351  if (t == hadw1_label) {
352  if (saw_hadw1)
353  t = hadw2_label;
354  saw_hadw1 = true;
355  }
356  ev.jet (i).type() = t;
357  }
358 }
359 
360 
361 } // unnamed namespace
362 
363 
364 //*************************************************************************
365 
366 
368  double lepw_mass,
369  double hadw_mass,
370  double top_mass)
371 //
372 // Purpose: Constructor.
373 //
374 // Inputs:
375 // args - The parameter settings for this instance.
376 // lepw_mass - The mass to which the leptonic W should be constrained,
377 // or 0 to skip this constraint.
378 // hadw_mass - The mass to which the hadronic W should be constrained,
379 // or 0 to skip this constraint.
380 // top_mass - The mass to which the top quarks should be constrained,
381 // or 0 to skip this constraint.
382 //
383  : _args (args),
384  _constrainer (args.constrainer_args(),
385  lepw_mass, hadw_mass, top_mass),
386  _lepw_mass(lepw_mass),
387  _hadw_mass (hadw_mass)
388 {
389 }
390 
391 
393  bool& nuz,
394  double& umwhad,
395  double& utmass,
396  double& mt,
397  double& sigmt,
398  Column_Vector& pullx,
399  Column_Vector& pully)
400 //
401 // Purpose: Fit a single jet permutation.
402 //
403 // Inputs:
404 // ev - The event to fit.
405 // The object labels must have already been assigned.
406 // nuz - Boolean flag to indicate which neutrino solution to be
407 // used.
408 // false = use smaller neutrino z solution
409 // true = use larger neutrino z solution
410 //
411 // Outputs:
412 // ev- The event after the fit.
413 // umwhad - Hadronic W mass before fitting.
414 // utmass - Top mass before fitting, averaged from both sides.
415 // mt - Top mass after fitting.
416 // sigmt - Top mass uncertainty after fitting.
417 // pullx - Vector of pull quantities for well-measured variables.
418 // pully - Vector of pull quantities for poorly-measured variables.
419 //
420 // Returns:
421 // The fit chisq, or < 0 if the fit didn't converge.
422 //
423 // Adaptation note by Haryo Sumowidagdo:
424 // This function is rewritten in order to make its purpose reflects
425 // the function's name. The function nows only fit one jet permutation
426 // with one neutrino solution only.
427 //
428 //
429 {
430  mt = 0;
431  sigmt = 0;
432 
433  // Find the neutrino solutions by requiring either:
434  // 1) that the leptonic top have the same mass as the hadronic top.
435  // 2) that the mass of the lepton and neutrino is equal to the W mass
436 
437  umwhad = Top_Decaykin::hadw (ev) . m();
438  double umthad = Top_Decaykin::hadt (ev) . m();
439  double nuz1, nuz2;
440 
441  if (_args.solve_nu_tmass()) {
442  Top_Decaykin::solve_nu_tmass (ev, umthad, nuz1, nuz2);
443  }
444  else {
445  Top_Decaykin::solve_nu (ev, _lepw_mass, nuz1, nuz2);
446  }
447 
448  // Set up to use the selected neutrino solution
449  if (!nuz) {
450  ev.met().setZ(nuz1);
451  }
452  else {
453  ev.met().setZ(nuz2);
454  }
455 
456  // Note: We have set the neutrino Pz, but we haven't set the neutrino energy.
457  // Remember that originally the neutrino energy was equal to
458  // sqrt(nu_px*nu_px + nu_py*nu_py). Calculating the invariant mass squared
459  // for the neutrino will give negative mass squared.
460  // Therefore we need to adjust (increase) the neutrino energy in order to
461  // make its mass remain zero.
462 
463  adjust_e_for_mass(ev.met(),0);
464 
465  // Find the unfit top mass as the average of the two sides.
466  double umtlep = Top_Decaykin::lept (ev) . m();
467  utmass = (umthad + umtlep) / 2;
468 
469  // Trace, if requested.
470  if (_args.print_event_flag()) {
471  cout << "Top_Fit::fit_one_perm() : Before fit:\n";
473  }
474 
475  // Maybe reject this event.
476  if (_hadw_mass > 0 && test_for_bad_masses (ev, _args, umwhad,
477  umthad, umtlep))
478  {
479  cout << "Top_Fit: bad mass comb.\n";
480  return -999;
481  }
482 
483  // Do the fit.
484  double chisq = _constrainer.constrain (ev, mt, sigmt, pullx, pully);
485 
486  // Trace, if requested.
487  if (_args.print_event_flag()) {
488  cout << "Top_Fit::fit_one_perm() : After fit:\n";
489  cout << "chisq: " << chisq << " mt: " << mt << " ";
491  }
492 
493  // Done!
494  return chisq;
495 }
496 
497 
499 //
500 // Purpose: Fit all jet permutations for EV.
501 //
502 // Inputs:
503 // ev - The event to fit.
504 //
505 // Returns:
506 // The results of the fit.
507 //
508 {
509  // Make a new Fit_Results object.
510  Fit_Results res (_args.nkeep(), n_lists);
511 
512  // Set up the vector of jet types.
513  vector<int> jet_types (ev.njets(), isr_label);
514  assert (ev.njets() >= 4);
515  jet_types[0] = lepb_label;
516  jet_types[1] = hadb_label;
517  jet_types[2] = hadw1_label;
518  jet_types[3] = hadw1_label;
519 
520  if (_args.do_higgs_flag() && ev.njets() >= 6) {
521  jet_types[4] = higgs_label;
522  jet_types[5] = higgs_label;
523  }
524 
525  // Must be in sorted order.
526  stable_sort (jet_types.begin(), jet_types.end());
527 
528  do {
529 
530  // Loop over the two possible neutrino solution
531  for (int nusol = 0 ; nusol != 2 ; nusol++) {
532 
533  // Set up the neutrino solution to be used
534  bool nuz = bool(nusol);
535 
536  // Copy the event.
537  Lepjets_Event fev = ev;
538 
539  // Install the new jet types.
540  set_jet_types (jet_types, fev);
541 
542  // Figure out on what lists this permutation should go.
543  vector<int> list_flags = classify_jetperm (jet_types, ev);
544 
545  // Set up the output variables for fit results.
546  double umwhad, utmass, mt, sigmt;
547  Column_Vector pullx;
548  Column_Vector pully;
549  double chisq;
550 
551  // Tracing.
552  cout << "Top_Fit::fit(): Before fit: (";
553  for (vector<int>::size_type i=0; i < jet_types.size(); i++) {
554  if (i) cout << " ";
555  cout << jet_types[i];
556  }
557  cout << " nuz = " << nuz ;
558  cout << ") " << std::endl;
559 
560  // Do the fit.
561  chisq = fit_one_perm (fev, nuz, umwhad, utmass, mt, sigmt, pullx, pully);
562 
563  // Print the result, if requested.
564  if (_args.print_event_flag()) {
565  cout << "Top_Fit::fit(): After fit:\n";
566  char buf[256];
567  sprintf (buf, "chisq: %8.3f mt: %6.2f pm %5.2f %c\n",
568  chisq, mt, sigmt, (list_flags[noperm_list] ? '*' : ' '));
569  cout << buf;
570  }
571 
572  // Add it to the results.
573  res.push (chisq, fev, pullx, pully, umwhad, utmass, mt, sigmt, list_flags);
574 
575  } // end of for loop over the two neutrino solution
576 
577  // Step to the next permutation.
578  } while (next_permutation (jet_types.begin(), jet_types.end()));
579 
580  return res;
581 }
582 
583 
592 std::ostream& operator<< (std::ostream& s, const Top_Fit& fitter)
593 //
594 // Purpose: Print the object to S.
595 //
596 // Inputs:
597 // s - The stream to which to write.
598 // fitter - The object to write.
599 //
600 // Returns:
601 // The stream S.
602 //
603 {
604  return s << fitter._constrainer;
605 }
606 
607 
609 {
610  return _args;
611 }
612 
613 } // namespace hitfit
static bool solve_nu_tmass(const Lepjets_Event &ev, double tmass, double &nuz1, double &nuz2)
Solve for the neutrino longitudinal momentum that makes the leptonic top have a certain value of mas...
Definition: Top_Decaykin.cc:81
bool solve_nu_tmass() const
Return the solve_nu_tmass parameter.
Definition: Top_Fit.cc:158
int i
Definition: DBlmapReader.cc:9
Hold on to parameters for the Constrained_Top class.
double _hadw_mass
Definition: Top_Fit.h:329
Define an abstract interface for getting parameter settings.
Top_Fit(const Top_Fit_Args &args, double lepw_mass, double hadw_mass, double top_mass)
Constructor.
Definition: Top_Fit.cc:367
Define three-vector and four-vector classes for the HitFit package, and supply a few additional opera...
Hold on to parameters for the Top_Fit class.
Definition: Top_Fit.h:77
double mwhad_min_cut() const
Return the mwhad_min_cut parameter.
Definition: Top_Fit.cc:118
double _mtdiff_max_cut
Definition: Top_Fit.h:198
void adjust_e_for_mass(Fourvec &v, double mass)
Adjust the energy component of four-vector v (leaving the three-vector part unchanged) so that the fo...
Definition: fourvec.cc:123
CLHEP::HepVector Column_Vector
Definition: matutil.h:66
double mwhad_max_cut() const
Return the mwhad_min_cut parameter.
Definition: Top_Fit.cc:128
bool ev
uint16_t size_type
bool print_event_flag() const
Return the print_event_flag parameter.
Definition: Top_Fit.cc:88
double fit_one_perm(Lepjets_Event &ev, bool &nuz, double &umwhad, double &utmass, double &mt, double &sigmt, Column_Vector &pullx, Column_Vector &pully)
Fit for a single jet permutation.
Definition: Top_Fit.cc:392
const Top_Fit_Args _args
Definition: Top_Fit.h:326
double jet_mass_cut() const
Return the jet_mass_cut parameter.
Definition: Top_Fit.cc:108
static bool solve_nu(const Lepjets_Event &ev, double wmass, double &nuz1, double &nuz2)
Solve for the longitudinal momentum that makes the leptonic -boson to have a certain value of mass...
double _mwhad_min_cut
Definition: Top_Fit.h:186
Represent a simple event consisting of lepton(s) and jet(s).
double _jet_mass_cut
Definition: Top_Fit.h:180
std::vector< Lepjets_Event_Jet >::size_type njets() const
Return the number of jets in the event.
A class to hold functions to calculate kinematic quantities of interest in events.
Represent a simple event consisting of lepton(s) and jet(s). An instance of this class holds a list o...
Definition: Lepjets_Event.h:66
const Constrained_Top_Args & constrainer_args() const
Definition: Top_Fit.cc:168
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Fit_Results fit(const Lepjets_Event &ev)
Fit all jets permutations in ev. This function returns a Fit_Results object, which is not easy to ext...
Definition: Top_Fit.cc:498
double constrain(Lepjets_Event &ev, double &mt, double &sigmt, Column_Vector &pullx, Column_Vector &pully)
Do a constrained fit of events. Returns the top mass and its error in mt and sigmt, and the pull quantities in pullx and pully. Returns the , this will be negative if the fit failed to converge.
double mtdiff_max_cut() const
Return the mwhad_max_cut parameter.
Definition: Top_Fit.cc:138
Handle and fit jet permutations of an event. This is the primary interface between user&#39;s Lepjets_Eve...
Top_Fit_Args(const Defaults &defs)
Constructor, initialize an instance of Top_Fit_Args from an instance of Defaults object.
Definition: Top_Fit.cc:68
Fourvec sum(int type) const
Return the sum of all objects&#39; four-momentum which have a particular type.
Constrained_Top_Args _args
Definition: Top_Fit.h:231
tuple out
Definition: dbtoconf.py:99
double _mwhad_max_cut
Definition: Top_Fit.h:192
Fourvec & met()
Return a reference to the missing transverse energy.
static Fourvec hadt(const Lepjets_Event &ev)
Sum up the appropriate four-momenta to find the hadronic top quark.
const Top_Fit_Args & args() const
Return a constant reference to the fit arguments.
Definition: Top_Fit.cc:608
Constrained_Top _constrainer
Definition: Top_Fit.h:327
double _lepw_mass
Definition: Top_Fit.h:328
string const
Definition: compareJSON.py:14
static Fourvec lept(const Lepjets_Event &ev)
Sum up the appropriate four-momenta to find the leptonic top quark.
Hold set(s) of results from more than one kinematic fits. Each set correspond to some subset of jet p...
Define an interface for getting parameter settings.
Definition: Defaults.h:61
std::ostream & operator<<(std::ostream &s, const Constraint_Intermed &ci)
Output stream operator, print the content of this Constraint_Intermed to an output stream...
bool do_higgs_flag() const
Return the do_higgs_flag parameter.
Definition: Top_Fit.cc:98
tuple cout
Definition: gather_cfg.py:121
int nkeep() const
Return the nkeep parameter.
Definition: Top_Fit.cc:148
Handle and fit jet permutations of an event. This is the primary interface between user&#39;s Lepjets_Eve...
Definition: Top_Fit.h:243
static Fourvec hadw(const Lepjets_Event &ev)
Sum up the appropriate four-momenta to find the hadronic boson.
Holds set(s) of results from more than one kinematic fits.
Definition: Fit_Results.h:59
static std::ostream & dump_ev(std::ostream &s, const Lepjets_Event &ev)
Print the kinematic information for an event.