CMS 3D CMS Logo

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.
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
double mtdiff_max_cut() const
Return the mwhad_max_cut parameter.
Definition: Top_Fit.cc:126
Hold on to parameters for the Constrained_Top class.
bool do_higgs_flag() const
Return the do_higgs_flag parameter.
Definition: Top_Fit.cc:90
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 _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
assert(be >=bs)
uint16_t size_type
Definition: Electron.h:6
bool solve_nu_tmass() const
Return the solve_nu_tmass parameter.
Definition: Top_Fit.cc:144
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 mwhad_max_cut() const
Return the mwhad_min_cut parameter.
Definition: Top_Fit.cc:117
const Constrained_Top_Args & constrainer_args() const
Definition: Top_Fit.cc:153
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
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
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.
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
Constrained_Top_Args _args
Definition: Top_Fit.h:222
double _mwhad_max_cut
Definition: Top_Fit.h:183
static Fourvec hadt(const Lepjets_Event &ev)
Sum up the appropriate four-momenta to find the hadronic top quark.
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.
const Top_Fit_Args & args() const
Return a constant reference to the fit arguments.
Definition: Top_Fit.cc:563
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...
double jet_mass_cut() const
Return the jet_mass_cut parameter.
Definition: Top_Fit.cc:99
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
double mwhad_min_cut() const
Return the mwhad_min_cut parameter.
Definition: Top_Fit.cc:108
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.
bool print_event_flag() const
Return the print_event_flag parameter.
Definition: Top_Fit.cc:81