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