CMS 3D CMS Logo

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