ATLAS Offline Software
TElectronLikelihoodTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3  */
4 
6 #include "TFile.h" // for TFile
7 #include "TH1.h" // for TH1F
8 #include "TROOT.h"
9 #include "TString.h" // for TString
10 #include "TSystem.h"
11 #include <algorithm> // for min
12 #include <cmath>
13 #include <cstdio> // for sprintf
14 #include <fstream> // for char_traits
15 
17 
23 //=============================================================================
24 // Constructor
25 //=============================================================================
26 
27 //----------------------------------------------------------------------------------------
29  : asg::AsgMessaging(std::string(name))
30  , m_doRemoveF3AtHighEt(false)
31  , m_doRemoveTRTPIDAtHighEt(false)
32  , m_doSmoothBinInterpolation(false)
33  , m_useOneExtraHighETLHBin(false)
34  , m_highETBinThreshold(125)
35  , m_doPileupTransform(false)
36  , m_doCentralityTransform(false)
37  , m_discMaxForPileupTransform(2.0)
38  , m_pileupMaxForPileupTransform(50)
39  , m_variableNames("")
40  , m_pdfFileName("")
41  , m_name(name)
42  , m_variableBitMask(0x0)
43  , m_ipBinning("")
44  , m_cutPosition_kinematic(-9)
45  , m_cutPosition_NSilicon(-9)
46  , m_cutPosition_NPixel(-9)
47  , m_cutPosition_NBlayer(-9)
48  , m_cutPosition_ambiguity(-9)
49  , m_cutPosition_LH(-9)
50  , m_cutPositionTrackA0(-9)
51  , m_cutPositionTrackMatchEta(-9)
52  , m_cutPositionTrackMatchPhiRes(-9)
53  , m_cutPositionWstotAtHighET(-9)
54  , m_cutPositionEoverPAtHighET(-9)
55 {
56  for (unsigned int varIndex = 0; varIndex < s_fnVariables; varIndex++) {
57  for (auto & fPDFbin : fPDFbins) {
58  for (auto & ip : fPDFbin) {
59  for (unsigned int et = 0; et < s_fnEtBinsHist; et++) {
60  for (unsigned int eta = 0; eta < s_fnEtaBins; eta++) {
61  ip[et][eta][varIndex] = nullptr;
62  }
63  }
64  }
65  }
66  }
67 }
68 
69 //=============================================================================
70 // Destructor
71 //=============================================================================
73 {
74  for (unsigned int varIndex = 0; varIndex < s_fnVariables; varIndex++) {
75  for (auto & fPDFbin : fPDFbins) {
76  for (auto & ip : fPDFbin) {
77  for (unsigned int et = 0; et < s_fnEtBinsHist; et++) {
78  for (unsigned int eta = 0; eta < s_fnEtaBins; eta++) {
79  if (ip[et][eta][varIndex]) {
80  delete ip[et][eta][varIndex];
81  ip[et][eta][varIndex] = nullptr;
82  }
83  }
84  }
85  }
86  }
87  }
88 }
89 
92 {
93  ATH_MSG_DEBUG("TElectronLikelihoodTool initialize.");
94 
95  // use an int as a StatusCode
96  StatusCode sc(StatusCode::SUCCESS);
97 
98  // Check that all needed variables are setup
99  if (m_pdfFileName.empty()) {
100  ATH_MSG_WARNING("You need to specify the input PDF file name before you "
101  "call initialize() with "
102  "setPDFFileName('your/file/name.root') ");
103  sc = StatusCode::FAILURE;
104  }
105 
106  unsigned int number_of_expected_bin_combinedLH;
107  if (m_useOneExtraHighETLHBin)
108  number_of_expected_bin_combinedLH = s_fnDiscEtBinsOneExtra * s_fnEtaBins;
109  else
110  number_of_expected_bin_combinedLH = s_fnDiscEtBins * s_fnEtaBins;
111  unsigned int number_of_expected_bin_combinedOther =
112  s_fnDiscEtBins * s_fnEtaBins;
113 
114  if (m_cutLikelihood.size() != number_of_expected_bin_combinedLH) {
115  ATH_MSG_ERROR("Configuration issue : cutLikelihood expected size "
116  << number_of_expected_bin_combinedLH << " input size "
117  << m_cutLikelihood.size());
118  sc = StatusCode::FAILURE;
119  }
120 
121  if (!m_discHardCutForPileupTransform.empty()) {
122  if (m_discHardCutForPileupTransform.size() !=
123  number_of_expected_bin_combinedLH) {
125  "Configuration issue : DiscHardCutForPileupTransform expected size "
126  << number_of_expected_bin_combinedLH << " input size "
127  << m_discHardCutForPileupTransform.size());
128  sc = StatusCode::FAILURE;
129  }
130  }
131  if (!m_discHardCutSlopeForPileupTransform.empty()) {
132  if (m_discHardCutSlopeForPileupTransform.size() !=
133  number_of_expected_bin_combinedLH) {
134  ATH_MSG_ERROR("Configuration issue : "
135  "DiscHardCutSlopeForPileupTransform expected size "
136  << number_of_expected_bin_combinedLH << " input size "
137  << m_discHardCutSlopeForPileupTransform.size());
138  sc = StatusCode::FAILURE;
139  }
140  }
141  if (!m_discLooseForPileupTransform.empty()) {
142  if (m_discLooseForPileupTransform.size() !=
143  number_of_expected_bin_combinedLH) {
145  "Configuration issue : DiscLooseForPileupTransform expected size "
146  << number_of_expected_bin_combinedLH << " input size "
147  << m_discLooseForPileupTransform.size());
148  sc = StatusCode::FAILURE;
149  }
150  }
151 
152  // d0 cut
153  if (!m_cutA0.empty()) {
154  if (m_cutA0.size() != number_of_expected_bin_combinedOther) {
155  ATH_MSG_ERROR("Configuration issue : CutA0 expected size "
156  << number_of_expected_bin_combinedOther << " input size "
157  << m_cutA0.size());
158  sc = StatusCode::FAILURE;
159  }
160  }
161 
162  // deltaEta cut
163  if (!m_cutDeltaEta.empty()) {
164  if (m_cutDeltaEta.size() != number_of_expected_bin_combinedOther) {
165  ATH_MSG_ERROR("Configuration issue : CutDeltaEta expected size "
166  << number_of_expected_bin_combinedOther << " input size "
167  << m_cutDeltaEta.size());
168  sc = StatusCode::FAILURE;
169  }
170  }
171 
172  // deltaPhiRes cut
173  if (!m_cutDeltaPhiRes.empty()) {
174  if (m_cutDeltaPhiRes.size() != number_of_expected_bin_combinedOther) {
175  ATH_MSG_ERROR("Configuration issue : CutDeltaPhiRes expected size "
176  << number_of_expected_bin_combinedOther << " input size "
177  << m_cutDeltaPhiRes.size());
178  sc = StatusCode::FAILURE;
179  }
180  }
181  if (sc == StatusCode::FAILURE) {
183  "Could NOT initialize! Please fix the errors mentioned above...");
184  return sc;
185  }
186 
187  // --------------------------------------------------------------------------
188  // Register the cuts and check that the registration worked:
189  // NOTE: THE ORDER IS IMPORTANT!!! Cut0 corresponds to bit 0, Cut1 to bit
190  // 1,... Cut position for the kineatic pre-selection
191  m_cutPosition_kinematic = m_acceptInfo.addCut("kinematic", "pass kinematic");
192  if (m_cutPosition_kinematic < 0) {
193  sc = StatusCode::FAILURE;
194  }
195 
196  // NSilicon
197  m_cutPosition_NSilicon = m_acceptInfo.addCut("NSilicon", "pass NSilicon");
198  if (m_cutPosition_NSilicon < 0) {
199  sc = StatusCode::FAILURE;
200  }
201 
202  // NPixel
203  m_cutPosition_NPixel = m_acceptInfo.addCut("NPixel", "pass NPixel");
204  if (m_cutPosition_NPixel < 0) {
205  sc = StatusCode::FAILURE;
206  }
207 
208  // NBlayer
209  m_cutPosition_NBlayer = m_acceptInfo.addCut("NBlayer", "pass NBlayer");
210  if (m_cutPosition_NBlayer < 0) {
211  sc = StatusCode::FAILURE;
212  }
213 
214  // Ambiguity
215  m_cutPosition_ambiguity = m_acceptInfo.addCut("ambiguity", "pass ambiguity");
216  if (m_cutPosition_ambiguity < 0) {
217  sc = StatusCode::FAILURE;
218  }
219 
220  // Cut position for the likelihood selection - DO NOT CHANGE ORDER!
221  m_cutPosition_LH = m_acceptInfo.addCut("passLH", "pass Likelihood");
222  if (m_cutPosition_LH < 0) {
223  sc = StatusCode::FAILURE;
224  }
225 
226  // D0
227  m_cutPositionTrackA0 =
228  m_acceptInfo.addCut("TrackA0", "A0 (aka d0) wrt beam spot < Cut");
229  if (m_cutPositionTrackA0 < 0) {
230  sc = StatusCode::FAILURE;
231  }
232 
233  // deltaeta
234  m_cutPositionTrackMatchEta = m_acceptInfo.addCut(
235  "TrackMatchEta", "Track match deta in 1st sampling < Cut");
236  if (m_cutPositionTrackMatchEta < 0) {
237  sc = StatusCode::FAILURE;
238  }
239 
240  // deltaphi
241  m_cutPositionTrackMatchPhiRes = m_acceptInfo.addCut(
242  "TrackMatchPhiRes", "Track match dphi in 2nd sampling, rescaled < Cut");
243  if (m_cutPositionTrackMatchPhiRes < 0) {
244  sc = StatusCode::FAILURE;
245  }
246 
247  // Wstot
248  m_cutPositionWstotAtHighET = m_acceptInfo.addCut(
249  "WstotAtHighET", "Above HighETBinThreshold, Wstot < Cut");
250  if (m_cutPositionWstotAtHighET < 0) {
251  sc = StatusCode::FAILURE;
252  }
253 
254  // EoverP
255  m_cutPositionEoverPAtHighET = m_acceptInfo.addCut(
256  "EoverPAtHighET", "Above HighETBinThreshold, EoverP < Cut");
257  if (m_cutPositionEoverPAtHighET < 0) {
258  sc = StatusCode::FAILURE;
259  }
260 
261  // Check that we got everything OK
262  if (sc == StatusCode::FAILURE) {
264  "! Something went wrong with the setup of the decision objects...");
265  return sc;
266  }
267 
268  // ----------------------------------
269  // Get the correct bit mask for the current likelihood operating point
270  m_variableBitMask = getLikelihoodBitmask(m_variableNames);
271 
272  //----------File/Histo operation------------------------------------
273  // Load the ROOT file containing the PDFs
274  TString tmpString(m_pdfFileName);
275  gSystem->ExpandPathName(tmpString);
276  std::string fname(tmpString.Data());
277  auto pdfFile = std::unique_ptr<TFile>(TFile::Open(fname.c_str(), "READ"));
278  // Check that we could load the ROOT file
279  if (!pdfFile) {
280  ATH_MSG_ERROR(" No ROOT file found here: " << m_pdfFileName);
281  return StatusCode::FAILURE;
282  }
283 
284  // Load the histograms
285  for (unsigned int varIndex = 0; varIndex < s_fnVariables; varIndex++) {
286  const std::string& vstr = s_fVariables[varIndex];
287  // Skip the loading of PDFs for variables we don't care about for this
288  // operating point. If the string is empty (which is true in the default
289  // 2012 case), load all of them.
290  if (m_variableNames.find(vstr) == std::string::npos &&
291  !m_variableNames.empty()) {
292  continue;
293  }
294  loadVarHistograms(vstr, pdfFile.get(), varIndex);
295  }
296 
297  // TFile close does not free the memory
298  pdfFile->Close();
299  //----------End File/Histo operation------------------------------------
300 
301  ATH_MSG_DEBUG("Initialization complete for a LH tool with these specs:"
302  << "\n - pdfFileName : "
303  << m_pdfFileName
304  << "\n - Variable bitmask : "
305  << m_variableBitMask);
306 
307  ATH_MSG_DEBUG("\n - VariableNames : "
308  << m_variableNames
309  << "\n - (bool)CutBL (yes/no) : "
310  << (!m_cutBL.empty() ? "yes" : "no")
311  << "\n - (bool)CutPi (yes/no) : "
312  << (!m_cutPi.empty() ? "yes" : "no")
313  << "\n - (bool)CutSi (yes/no) : "
314  << (!m_cutSi.empty() ? "yes" : "no")
315  << "\n - (bool)CutAmbiguity (yes/no) : "
316  << (!m_cutAmbiguity.empty() ? "yes" : "no")
317  << "\n - (bool)doRemoveF3AtHighEt (yes/no) : "
318  << (m_doRemoveF3AtHighEt ? "yes" : "no")
319  << "\n - (bool)doRemoveTRTPIDAtHighEt (yes/no) : "
320  << (m_doRemoveTRTPIDAtHighEt ? "yes" : "no")
321  << "\n - (bool)doSmoothBinInterpolation (yes/no) : "
322  << (m_doSmoothBinInterpolation ? "yes" : "no")
323  << "\n - (bool)useOneExtraHighETLHBin(yes/no) : "
324  << (m_useOneExtraHighETLHBin ? "yes" : "no")
325  << "\n - (double)HighETBinThreshold : "
326  << m_highETBinThreshold
327  << "\n - (bool)doPileupTransform (yes/no) : "
328  << (m_doPileupTransform ? "yes" : "no")
329  << "\n - (bool)doCentralityTransform (yes/no) : "
330  << (m_doCentralityTransform ? "yes" : "no")
331  << "\n - (bool)CutLikelihood (yes/no) : "
332  << (!m_cutLikelihood.empty() ? "yes" : "no")
333  << "\n - (bool)CutLikelihoodPileupCorrection (yes/no) : "
334  << (!m_cutLikelihoodPileupCorrection.empty() ? "yes" : "no")
335  << "\n - (bool)CutA0 (yes/no) : "
336  << (!m_cutA0.empty() ? "yes" : "no")
337  << "\n - (bool)CutDeltaEta (yes/no) : "
338  << (!m_cutDeltaEta.empty() ? "yes" : "no")
339  << "\n - (bool)CutDeltaPhiRes (yes/no) : "
340  << (!m_cutDeltaPhiRes.empty() ? "yes" : "no")
341  << "\n - (bool)CutWstotAtHighET (yes/no) : "
342  << (!m_cutWstotAtHighET.empty() ? "yes" : "no")
343  << "\n - (bool)CutEoverPAtHighET (yes/no) : "
344  << (!m_cutEoverPAtHighET.empty() ? "yes" : "no"));
345  return sc;
346 }
347 
348 int
350  TFile* pdfFile,
351  unsigned int varIndex)
352 {
353  for (unsigned int s_or_b = 0; s_or_b < 2; ++s_or_b) {
354  for (unsigned int ip = 0; ip < IP_BINS; ++ip) {
355  for (unsigned int et = 0; et < s_fnEtBinsHist; ++et) {
356  for (unsigned int eta = 0; eta < s_fnEtaBins; ++eta) {
357 
358  std::string sig_bkg = (s_or_b == 0) ? "sig" : "bkg";
359  // Because eta bins in the root file don't match up exactly with cut
360  // menu definitions, the second eta bin is an exact copy of the first,
361  // and all subsequent eta bins are pushed back by one.
362  unsigned int eta_tmp = (eta > 0) ? eta - 1 : eta;
363  // The 7-10 GeV, crack bin uses the 10-15 Gev pdfs. WE DO NOT DO THIS
364  // ANYMORE! unsigned int et_tmp = (eta == 5 && et == 1) ? 1 : et;
365  unsigned int et_tmp = et;
366  char binname[200];
367  getBinName(binname, et_tmp, eta_tmp, ip, m_ipBinning);
368 
369  if (((std::string(binname).find("2.37") != std::string::npos)) &&
370  (vstr.find("el_f3") != std::string::npos)) {
371  continue;
372  }
373 
374  if (((std::string(binname).find("2.01") != std::string::npos) ||
375  (std::string(binname).find("2.37") != std::string::npos)) &&
376  (vstr.find("TRT") != std::string::npos)) {
377  continue;
378  }
379 
380  char pdfdir[500];
381  snprintf(pdfdir, 500, "%s/%s", vstr.c_str(), sig_bkg.c_str());
382  char pdf[500];
383  snprintf(pdf,
384  500,
385  "%s_%s_smoothed_hist_from_KDE_%s",
386  vstr.c_str(),
387  sig_bkg.c_str(),
388  binname);
389  char pdf_newname[500];
390  snprintf(pdf_newname,
391  500,
392  "%s_%s_%s_LHtool_copy_%s",
393  m_name.c_str(),
394  vstr.c_str(),
395  sig_bkg.c_str(),
396  binname);
397 
398  if (!pdfFile->GetListOfKeys()->Contains(vstr.c_str())) {
399  ATH_MSG_INFO("Warning: skipping variable "
400  << vstr << " because the folder does not exist.");
401  return 1;
402  }
403  if (!((TDirectory*)pdfFile->Get(vstr.c_str()))
404  ->GetListOfKeys()
405  ->Contains(sig_bkg.c_str())) {
406  ATH_MSG_INFO("Warning: skipping variable "
407  << vstr << " because the folder does not exist.");
408  return 1;
409  }
410 
411  // If the 0th et bin (4-7 GeV) histogram does not exist in the root
412  // file, then just use the 7-10 GeV bin histogram. This should
413  // preserve backward compatibility
414  if (et == 0 && !((TDirectory*)pdfFile->Get(pdfdir))
415  ->GetListOfKeys()
416  ->Contains(pdf)) {
417  getBinName(binname, et_tmp + 1, eta_tmp, ip, m_ipBinning);
418  snprintf(pdf,
419  500,
420  "%s_%s_smoothed_hist_from_KDE_%s",
421  vstr.c_str(),
422  sig_bkg.c_str(),
423  binname);
424  snprintf(pdf_newname,
425  500,
426  "%s_%s_%s_LHtool_copy4GeV_%s",
427  m_name.c_str(),
428  vstr.c_str(),
429  sig_bkg.c_str(),
430  binname);
431  }
432  if (((TDirectory*)pdfFile->Get(pdfdir))
433  ->GetListOfKeys()
434  ->Contains(pdf)) {
435  TH1F* hist = (TH1F*)(((TDirectory*)pdfFile->Get(pdfdir))->Get(pdf));
436  fPDFbins[s_or_b][ip][et][eta][varIndex] =
438  delete hist;
439  } else {
440  ATH_MSG_INFO("Warning: Object " << pdf << " does not exist.");
441  ATH_MSG_INFO("Skipping all other histograms with this variable.");
442  return 1;
443  }
444  }
445  }
446  }
447  }
448  return 1;
449 }
450 
453  double eta,
454  double eT,
455  int nSiHitsPlusDeadSensors,
458  uint8_t ambiguityBit,
459  double d0,
460  double deltaEta,
461  double deltaphires,
462  double wstot,
463  double EoverP,
464  double ip) const
465 {
467  vars.likelihood = likelihood;
468  vars.eta = eta;
469  vars.eT = eT;
470  vars.nSiHitsPlusDeadSensors = nSiHitsPlusDeadSensors;
471  vars.nPixHitsPlusDeadSensors = nPixHitsPlusDeadSensors;
472  vars.passBLayerRequirement = passBLayerRequirement;
473  vars.ambiguityBit = ambiguityBit;
474  vars.d0 = d0;
475  vars.deltaEta = deltaEta;
476  vars.deltaphires = deltaphires;
477  vars.wstot = wstot;
478  vars.EoverP = EoverP;
479  vars.ip = ip;
480 
481  return accept(vars);
482 }
483 
484 // This method calculates if the current electron passes the requested
485 // likelihood cut
488  LikeEnum::LHAcceptVars_t& vars_struct) const
489 {
490  // Setup return accept with AcceptInfo
491  asg::AcceptData acceptData(&m_acceptInfo);
492 
493  // Set up the individual cuts
494  bool passKine(true);
495  bool passNSilicon(true);
496  bool passNPixel(true);
497  bool passNBlayer(true);
498  bool passAmbiguity(true);
499  bool passLH(true);
500  bool passTrackA0(true);
501  bool passDeltaEta(true);
502  bool passDeltaPhiRes(true);
503  bool passWstotAtHighET(true);
504  bool passEoverPAtHighET(true);
505 
506  if (std::abs(vars_struct.eta) > 2.47) {
507  ATH_MSG_DEBUG("This electron is std::abs(eta)>2.47 Returning False.");
508  passKine = false;
509  }
510 
511  unsigned int etbinLH = getLikelihoodEtDiscBin(vars_struct.eT, true);
512  unsigned int etbinOther = getLikelihoodEtDiscBin(vars_struct.eT, false);
513  unsigned int etabin = getLikelihoodEtaBin(vars_struct.eta);
514 
515  // sanity
516  if (etbinLH >= s_fnDiscEtBinsOneExtra) {
517  ATH_MSG_WARNING("Cannot evaluate likelihood for Et "
518  << vars_struct.eT << ". Returning false..");
519  passKine = false;
520  }
521  // sanity
522  if (etbinOther >= s_fnDiscEtBins) {
523  ATH_MSG_WARNING("Cannot evaluate likelihood for Et "
524  << vars_struct.eT << ". Returning false..");
525  passKine = false;
526  }
527 
528  // Return if the kinematic requirements are not fulfilled
529  acceptData.setCutResult(m_cutPosition_kinematic, passKine);
530  if (!passKine) {
531  return acceptData;
532  }
533 
534  // ambiguity bit
535  if (!m_cutAmbiguity.empty()) {
538  m_cutAmbiguity[etabin])) {
539  ATH_MSG_DEBUG("Likelihood macro: ambiguity Bit Failed.");
540  passAmbiguity = false;
541  }
542  }
543 
544  // blayer cut
545  if (!m_cutBL.empty()) {
546  if (m_cutBL[etabin] == 1 && !vars_struct.passBLayerRequirement) {
547  ATH_MSG_DEBUG("Likelihood macro: Blayer cut failed.");
548  passNBlayer = false;
549  }
550  }
551  // pixel cut
552  if (!m_cutPi.empty()) {
553  if (vars_struct.nPixHitsPlusDeadSensors < m_cutPi[etabin]) {
554  ATH_MSG_DEBUG("Likelihood macro: Pixels Failed.");
555  passNPixel = false;
556  }
557  }
558  // silicon cut
559  if (!m_cutSi.empty()) {
560  if (vars_struct.nSiHitsPlusDeadSensors < m_cutSi[etabin]) {
561  ATH_MSG_DEBUG("Likelihood macro: Silicon Failed.");
562  passNSilicon = false;
563  }
564  }
565 
566  double cutDiscriminant;
567  unsigned int ibin_combinedLH =
568  etbinLH * s_fnEtaBins + etabin; // Must change if number of eta bins
569  // changes!. Also starts from 7-10 GeV bin.
570  unsigned int ibin_combinedOther =
571  etbinOther * s_fnEtaBins +
572  etabin; // Must change if number of eta bins changes!. Also
573  // starts from 7-10 GeV bin.
574 
575  if (!m_cutLikelihood.empty()) {
576  // To protect against a binning mismatch, which should never happen
577  if (ibin_combinedLH >= m_cutLikelihood.size()) {
578  ATH_MSG_ERROR("The desired eta/pt bin "
579  << ibin_combinedLH
580  << " is outside of the range specified by the input"
581  << m_cutLikelihood.size() << "This should never happen!");
582  return acceptData;
583  }
584 
585  if (m_doSmoothBinInterpolation) {
586  cutDiscriminant = InterpolateCuts(
587  m_cutLikelihood, m_cutLikelihood4GeV, vars_struct.eT, vars_struct.eta);
588  if (!m_doPileupTransform && !m_cutLikelihoodPileupCorrection.empty() &&
589  !m_cutLikelihoodPileupCorrection4GeV.empty())
590  cutDiscriminant +=
591  vars_struct.ip * InterpolateCuts(m_cutLikelihoodPileupCorrection,
592  m_cutLikelihoodPileupCorrection4GeV,
593  vars_struct.eT,
594  vars_struct.eta);
595  } else {
596  if (vars_struct.eT > 7000. || m_cutLikelihood4GeV.empty()) {
597  cutDiscriminant = m_cutLikelihood[ibin_combinedLH];
598  // If doPileupTransform, then correct the discriminant itself instead of
599  // the cut value
600  if (!m_doPileupTransform && !m_cutLikelihoodPileupCorrection.empty()) {
601  cutDiscriminant +=
602  vars_struct.ip * m_cutLikelihoodPileupCorrection[ibin_combinedLH];
603  }
604  } else {
605  cutDiscriminant = m_cutLikelihood4GeV[etabin];
606  if (!m_doPileupTransform &&
607  !m_cutLikelihoodPileupCorrection4GeV.empty())
608  cutDiscriminant +=
609  vars_struct.ip * m_cutLikelihoodPileupCorrection4GeV[etabin];
610  }
611  }
612 
613  // Determine if the calculated likelihood value passes the cut
614  ATH_MSG_DEBUG("Likelihood macro: Discriminant: ");
615  if (vars_struct.likelihood < cutDiscriminant) {
616  ATH_MSG_DEBUG("Likelihood macro: Disciminant Cut Failed.");
617  passLH = false;
618  }
619  }
620 
621  // d0 cut
622  if (!m_cutA0.empty()) {
623  if (std::abs(vars_struct.d0) > m_cutA0[ibin_combinedOther]) {
624  ATH_MSG_DEBUG("Likelihood macro: D0 Failed.");
625  passTrackA0 = false;
626  }
627  }
628 
629  // deltaEta cut
630  if (!m_cutDeltaEta.empty()) {
631  if (std::abs(vars_struct.deltaEta) > m_cutDeltaEta[ibin_combinedOther]) {
632  ATH_MSG_DEBUG("Likelihood macro: deltaEta Failed.");
633  passDeltaEta = false;
634  }
635  }
636 
637  // deltaPhiRes cut
638  if (!m_cutDeltaPhiRes.empty()) {
639  if (std::abs(vars_struct.deltaphires) >
640  m_cutDeltaPhiRes[ibin_combinedOther]) {
641  ATH_MSG_DEBUG("Likelihood macro: deltaphires Failed.");
642  passDeltaPhiRes = false;
643  }
644  }
645 
646  // Only do this above HighETBinThreshold [in GeV]
647  if (vars_struct.eT > m_highETBinThreshold * 1000) {
648  // wstot cut
649  if (!m_cutWstotAtHighET.empty()) {
650  if (std::abs(vars_struct.wstot) > m_cutWstotAtHighET[etabin]) {
651  ATH_MSG_DEBUG("Likelihood macro: wstot Failed.");
652  passWstotAtHighET = false;
653  }
654  }
655 
656  // EoverP cut
657  if (!m_cutEoverPAtHighET.empty()) {
658  if (std::abs(vars_struct.EoverP) > m_cutEoverPAtHighET[etabin]) {
659  ATH_MSG_DEBUG("Likelihood macro: EoverP Failed.");
660  passEoverPAtHighET = false;
661  }
662  }
663  }
664 
665  // Set the individual cut bits in the return object
666  acceptData.setCutResult(m_cutPosition_NSilicon, passNSilicon);
667  acceptData.setCutResult(m_cutPosition_NPixel, passNPixel);
668  acceptData.setCutResult(m_cutPosition_NBlayer, passNBlayer);
669  acceptData.setCutResult(m_cutPosition_ambiguity, passAmbiguity);
670  acceptData.setCutResult(m_cutPosition_LH, passLH);
671  acceptData.setCutResult(m_cutPositionTrackA0, passTrackA0);
672  acceptData.setCutResult(m_cutPositionTrackMatchEta, passDeltaEta);
673  acceptData.setCutResult(m_cutPositionTrackMatchPhiRes, passDeltaPhiRes);
674  acceptData.setCutResult(m_cutPositionWstotAtHighET, passWstotAtHighET);
675  acceptData.setCutResult(m_cutPositionEoverPAtHighET, passEoverPAtHighET);
676  return acceptData;
677 }
678 
679 double
681  double eT,
682  double f3,
683  double rHad,
684  double rHad1,
685  double Reta,
686  double w2,
687  double f1,
688  double eratio,
689  double deltaEta,
690  double d0,
691  double d0sigma,
692  double rphi,
693  double deltaPoverP,
694  double deltaphires,
695  double TRT_PID,
696  double ip) const
697 {
698 
699  LikeEnum::LHCalcVars_t vars{};
700 
701  vars.eta = eta;
702  vars.eT = eT;
703  vars.f3 = f3;
704  vars.rHad = rHad;
705  vars.rHad1 = rHad1;
706  vars.Reta = Reta;
707  vars.w2 = w2;
708  vars.f1 = f1;
709  vars.eratio = eratio;
710  vars.deltaEta = deltaEta;
711  vars.d0 = d0;
712  vars.d0sigma = d0sigma;
713  vars.rphi = rphi;
714  vars.deltaPoverP = deltaPoverP;
715  vars.deltaphires = deltaphires;
716  vars.TRT_PID = TRT_PID;
717  vars.ip = ip;
718 
719  return calculate(vars);
720 }
721 
722 // The main public method to actually calculate the likelihood value
723 double
725  LikeEnum::LHCalcVars_t& vars_struct) const
726 {
727  // Reset the results to defaul values
728  double result = -999;
729 
730  unsigned int etabin = getLikelihoodEtaBin(vars_struct.eta);
731  double rhad_corr;
732  if (etabin == 3 || etabin == 4) {
733  rhad_corr = vars_struct.rHad;
734  } else {
735  rhad_corr = vars_struct.rHad1;
736  }
737  double d0significance = vars_struct.d0sigma == 0
738  ? 0.
739  : std::abs(vars_struct.d0) / vars_struct.d0sigma;
740 
741  std::vector<double> vec = {
742  d0significance, vars_struct.eratio, vars_struct.deltaEta,
743  vars_struct.f1, vars_struct.f3, vars_struct.Reta,
744  rhad_corr, vars_struct.rphi, vars_struct.d0,
745  vars_struct.w2, vars_struct.deltaPoverP, vars_struct.deltaphires,
746  vars_struct.TRT_PID
747  };
748  // Calculate the actual likelihood value and fill the return object
749  result = this->evaluateLikelihood(
750  vec, vars_struct.eT, vars_struct.eta, vars_struct.ip);
751 
752  return result;
753 }
754 
755 double
757  const std::vector<float>& varVector,
758  double et,
759  double eta,
760  double ip) const
761 {
762  std::vector<double> vec;
763  for (unsigned int var = 0; var < s_fnVariables; var++) {
764  vec.push_back(varVector[var]);
765  }
766  return evaluateLikelihood(vec, et, eta, ip);
767 }
768 
769 double
771  const std::vector<double>& varVector,
772  double et,
773  double eta,
774  double ip) const
775 {
776 
777  const double GeV = 1000;
778  unsigned int etbin = getLikelihoodEtHistBin(et); // hist binning
779  unsigned int etabin = getLikelihoodEtaBin(eta);
780  unsigned int ipbin = getIpBin(ip);
781 
782  ATH_MSG_DEBUG("et: " << et << " eta: " << eta << " etbin: " << etbin
783  << " etabin: " << etabin);
784 
785  if (etbin >= s_fnEtBinsHist) {
786  ATH_MSG_WARNING("skipping etbin " << etbin << ", et " << et);
787  return -999.;
788  }
789  if (etabin >= s_fnEtaBins) {
790  ATH_MSG_WARNING("skipping etabin " << etabin << ", eta " << eta);
791  return -999.;
792  }
793 
794  if (varVector.size() != s_fnVariables) {
795  ATH_MSG_WARNING("Error! Variable vector size mismatch! Check your vector!");
796  }
797 
798  double SigmaS = 1.;
799  double SigmaB = 1.;
800 
801  // define some string constants
802  const std::string TRT_string = "TRT";
803  const std::string el_f3_string = "el_f3";
804  const std::string el_TRT_PID_string = "el_TRT_PID";
805 
806  for (unsigned int var = 0; var < s_fnVariables; var++) {
807 
808  const std::string& varstr = s_fVariables[var];
809 
810  // Skip variables that are masked off (not used) in the likelihood
811  if (!(m_variableBitMask & (0x1 << var))) {
812  continue;
813  }
814  // Don't use TRT for outer eta bins (2.01,2.37)
815  if (((etabin == 8) || (etabin == 9)) &&
816  (varstr.find(TRT_string) != std::string::npos)) {
817  continue;
818  }
819  // Don't use f3 for outer eta bin (2.37)
820  if ((etabin == 9) && (varstr.find(el_f3_string) != std::string::npos)) {
821  continue;
822  }
823  // Don't use f3 for high et (>80 GeV)
824  if (m_doRemoveF3AtHighEt && (et > 80 * GeV) &&
825  (varstr.find(el_f3_string) != std::string::npos)) {
826  continue;
827  }
828  // Don't use TRTPID for high et (>80 GeV)
829  if (m_doRemoveTRTPIDAtHighEt && (et > 80 * GeV) &&
830  (varstr.find(el_TRT_PID_string) != std::string::npos)) {
831  continue;
832  }
833  for (unsigned int s_or_b = 0; s_or_b < 2; s_or_b++) {
834 
835  int bin =
836  fPDFbins[s_or_b][ipbin][etbin][etabin][var]->FindBin(varVector[var]);
837 
838  double prob = 0;
839  if (m_doSmoothBinInterpolation) {
840  prob = InterpolatePdfs(s_or_b, ipbin, et, eta, bin, var);
841  } else {
842  double integral =
843  double(fPDFbins[s_or_b][ipbin][etbin][etabin][var]->Integral());
844  if (integral == 0) {
845  ATH_MSG_WARNING("Error! PDF integral == 0!");
846  return -1.35;
847  }
848 
849  prob =
850  double(
851  fPDFbins[s_or_b][ipbin][etbin][etabin][var]->GetBinContent(bin)) /
852  integral;
853  }
854 
855  if (s_or_b == 0) {
856  SigmaS *= prob;
857  } else if (s_or_b == 1) {
858  SigmaB *= prob;
859  }
860  }
861  }
862 
863  return TransformLikelihoodOutput(SigmaS, SigmaB, ip, et, eta);
864 }
865 
866 // --------------------------------------------
867 double
869  double pb,
870  double ip,
871  double et,
872  double eta) const
873 {
874  // returns transformed or non-transformed output
875  // (Taken mostly from TMVA likelihood code)
876  double fEpsilon = 1e-99;
877  // If both signal and bkg are 0, we want it to fail.
878  if (ps < fEpsilon)
879  ps = 0;
880  if (pb < fEpsilon)
881  pb = fEpsilon;
882  double disc = ps / double(ps + pb);
883 
884  if (disc >= 1.0) {
885  disc = 1. - 1.e-15;
886  } else if (disc <= 0.0) {
887  disc = fEpsilon;
888  }
889 
890  double tau = 15.0;
891  disc = -log(1.0 / disc - 1.0) * (1. / double(tau));
892 
893  // Linearly transform the discriminant as a function of pileup, rather than
894  // the old scheme of changing the cut value based on pileup. This is simpler
895  // for the tuning, as well as ensuring subsets / making discriminants more
896  // transparent. In the HI case, a quadratic centrality transform is applied
897  // instead.
898  if (m_doPileupTransform) {
899 
900  // The variables used by the transform:
901  //
902  // - hard_cut_ref = extremely tight discriminant cut as reference to ensure
903  // pileup correction for looser menus is less than for tighter menus.
904  // - loose_ref = a loose menu with no pileup correction. Any tighter
905  // menu with same inputs will necessarily have pileup dependence built in
906  // - disc_max = max disc value for which pileup correction is desired.
907  // - pileup_max = max nvtx or mu for calculating the transform. Any larger
908  // pileup values will use this maximum value in the transform.
909 
910  if (m_discHardCutForPileupTransform.empty() ||
911  m_discHardCutSlopeForPileupTransform.empty() ||
912  m_discLooseForPileupTransform.empty()) {
914  "Vectors needed for pileup-dependent transform not correctly filled! "
915  "Skipping the transform.");
916  return disc;
917  }
918 
919  if (m_doCentralityTransform &&
920  m_discHardCutQuadForPileupTransform.empty()) {
921  ATH_MSG_WARNING("Vectors needed for centrality-dependent transform not "
922  "correctly filled! "
923  "Skipping the transform.");
924  return disc;
925  }
926 
927  unsigned int etabin = getLikelihoodEtaBin(eta);
928 
929  double disc_hard_cut_ref = 0;
930  double disc_hard_cut_ref_slope = 0;
931  double disc_hard_cut_ref_quad =
932  0; // only used for heavy ion implementation of the LH
933  double disc_loose_ref = 0;
934  double disc_max = m_discMaxForPileupTransform;
935  double pileup_max = m_pileupMaxForPileupTransform;
936 
937  if (m_doSmoothBinInterpolation) {
938  disc_hard_cut_ref = InterpolateCuts(m_discHardCutForPileupTransform,
939  m_discHardCutForPileupTransform4GeV,
940  et,
941  eta);
942  disc_hard_cut_ref_slope =
943  InterpolateCuts(m_discHardCutSlopeForPileupTransform,
944  m_discHardCutSlopeForPileupTransform4GeV,
945  et,
946  eta);
947  if (m_doCentralityTransform)
948  disc_hard_cut_ref_quad =
949  InterpolateCuts(m_discHardCutQuadForPileupTransform,
950  m_discHardCutQuadForPileupTransform4GeV,
951  et,
952  eta);
953  disc_loose_ref = InterpolateCuts(m_discLooseForPileupTransform,
954  m_discLooseForPileupTransform4GeV,
955  et,
956  eta);
957  } else {
958  // default situation, in the case where 4-7 GeV bin is not defined
959  if (et > 7000. || m_discHardCutForPileupTransform4GeV.empty()) {
960  unsigned int etfinebinLH = getLikelihoodEtDiscBin(et, true);
961  unsigned int ibin_combined = etfinebinLH * s_fnEtaBins + etabin;
962  disc_hard_cut_ref = m_discHardCutForPileupTransform[ibin_combined];
963  disc_hard_cut_ref_slope =
964  m_discHardCutSlopeForPileupTransform[ibin_combined];
965  if (m_doCentralityTransform)
966  disc_hard_cut_ref_quad =
967  m_discHardCutQuadForPileupTransform[ibin_combined];
968  disc_loose_ref = m_discLooseForPileupTransform[ibin_combined];
969  } else {
970  if (m_discHardCutForPileupTransform4GeV.empty() ||
971  m_discHardCutSlopeForPileupTransform4GeV.empty() ||
972  m_discLooseForPileupTransform4GeV.empty()) {
973  ATH_MSG_WARNING("Vectors needed for pileup-dependent transform not "
974  "correctly filled for 4-7 GeV "
975  "bin! Skipping the transform.");
976  return disc;
977  }
978  if (m_doCentralityTransform &&
979  m_discHardCutQuadForPileupTransform4GeV.empty()) {
980  ATH_MSG_WARNING("Vectors needed for centrality-dependent transform "
981  "not correctly filled for 4-7 "
982  "GeV bin! Skipping the transform.");
983  return disc;
984  }
985  disc_hard_cut_ref = m_discHardCutForPileupTransform4GeV[etabin];
986  disc_hard_cut_ref_slope =
987  m_discHardCutSlopeForPileupTransform4GeV[etabin];
988  if (m_doCentralityTransform)
989  disc_hard_cut_ref_quad =
990  m_discHardCutQuadForPileupTransform4GeV[etabin];
991  disc_loose_ref = m_discLooseForPileupTransform4GeV[etabin];
992  }
993  }
994 
995  double ip_for_corr =
996  std::min(ip, pileup_max); // turn off correction for values > pileup_max
997  double disc_hard_cut_ref_prime =
998  disc_hard_cut_ref + disc_hard_cut_ref_slope * ip_for_corr +
999  disc_hard_cut_ref_quad * ip_for_corr * ip_for_corr;
1000 
1001  if (disc <= disc_loose_ref) {
1002  // Below threshold for applying pileup correction
1003  } else if (disc <= disc_hard_cut_ref_prime) {
1004  // Between the loose and hard cut reference points for pileup correction
1005  double denom = double(disc_hard_cut_ref_prime - disc_loose_ref);
1006  if (denom < 0.001)
1007  denom = 0.001;
1008  disc = disc_loose_ref + (disc - disc_loose_ref) *
1009  (disc_hard_cut_ref - disc_loose_ref) / denom;
1010  } else if (disc_hard_cut_ref_prime < disc && disc <= disc_max) {
1011  // Between the hard cut and max reference points for pileup correction
1012  double denom = double(disc_max - disc_hard_cut_ref_prime);
1013  if (denom < 0.001)
1014  denom = 0.001;
1015  disc = disc_hard_cut_ref + (disc - disc_hard_cut_ref_prime) *
1016  (disc_max - disc_hard_cut_ref) / denom;
1017  }
1018  }
1019 
1020  ATH_MSG_DEBUG("disc is " << disc);
1021  return disc;
1022 }
1023 
1024 //---------------------------------------------------------------------------------------
1025 // Gets the IP bin
1026 unsigned int
1028 {
1029  for (unsigned int ipBin = 0; ipBin < IP_BINS; ++ipBin) {
1030  if (ip < s_fIpBounds[ipBin + 1])
1031  return ipBin;
1032  }
1033  return 0;
1034 }
1035 
1036 //---------------------------------------------------------------------------------------
1037 // Gets the Eta bin [0-9] given the eta
1038 unsigned int
1040 {
1041  const unsigned int nEtaBins = s_fnEtaBins;
1042  const double etaBins[nEtaBins] = { 0.1, 0.6, 0.8, 1.15, 1.37,
1043  1.52, 1.81, 2.01, 2.37, 2.47 };
1044 
1045  for (unsigned int etaBin = 0; etaBin < nEtaBins; ++etaBin) {
1046  if (std::abs(eta) < etaBins[etaBin])
1047  return etaBin;
1048  }
1049 
1050  return 9;
1051 }
1052 //---------------------------------------------------------------------------------------
1053 // Gets the histogram Et bin given the et (MeV) -- corrresponds to fnEtBinsHist
1054 unsigned int
1056 {
1057  const double GeV = 1000;
1058 
1059  const unsigned int nEtBins = s_fnEtBinsHist;
1060  const double eTBins[nEtBins] = { 7 * GeV, 10 * GeV, 15 * GeV, 20 * GeV,
1061  30 * GeV, 40 * GeV, 50 * GeV };
1062 
1063  for (unsigned int eTBin = 0; eTBin < nEtBins; ++eTBin) {
1064  if (eT < eTBins[eTBin]) {
1065  return eTBin;
1066  }
1067  }
1068 
1069  return nEtBins - 1; // Return the last bin if > the last bin.
1070 }
1071 
1072 //---------------------------------------------------------------------------------------
1073 // Gets the Et bin [0-10] given the et (MeV)
1074 unsigned int
1076  double eT,
1077  const bool isLHbinning) const
1078 {
1079  const double GeV = 1000;
1080 
1081  if (m_useOneExtraHighETLHBin && isLHbinning) {
1082  const unsigned int nEtBins = s_fnDiscEtBinsOneExtra;
1083  const double eTBins[nEtBins] = {
1084  10 * GeV, 15 * GeV, 20 * GeV,
1085  25 * GeV, 30 * GeV, 35 * GeV,
1086  40 * GeV, 45 * GeV, m_highETBinThreshold * GeV,
1087  6000 * GeV
1088  };
1089 
1090  for (unsigned int eTBin = 0; eTBin < nEtBins; ++eTBin) {
1091  if (eT < eTBins[eTBin])
1092  return eTBin;
1093  }
1094 
1095  return nEtBins - 1; // Return the last bin if > the last bin.
1096  }
1097 
1098  const unsigned int nEtBins = s_fnDiscEtBins;
1099  const double eTBins[nEtBins] = { 10 * GeV, 15 * GeV, 20 * GeV,
1100  25 * GeV, 30 * GeV, 35 * GeV,
1101  40 * GeV, 45 * GeV, 50 * GeV };
1102 
1103  for (unsigned int eTBin = 0; eTBin < nEtBins; ++eTBin) {
1104  if (eT < eTBins[eTBin])
1105  return eTBin;
1106  }
1107 
1108  return nEtBins - 1; // Return the last bin if > the last bin.
1109 }
1110 
1111 //---------------------------------------------------------------------------------------
1112 // Gets the bin name. Given the HISTOGRAM binning (fnEtBinsHist)
1113 void
1115  int etbin,
1116  int etabin,
1117  int ipbin,
1118  const std::string& iptype)
1119 {
1120  double eta_bounds[9] = { 0.0, 0.6, 0.8, 1.15, 1.37, 1.52, 1.81, 2.01, 2.37 };
1121  int et_bounds[s_fnEtBinsHist] = { 4, 7, 10, 15, 20, 30, 40 };
1122  if (!iptype.empty()) {
1123  snprintf(buffer,
1124  200,
1125  "%s%det%02deta%0.2f",
1126  iptype.c_str(),
1127  int(s_fIpBounds[ipbin]),
1128  et_bounds[etbin],
1129  eta_bounds[etabin]);
1130  } else {
1131  snprintf(buffer, 200, "et%deta%0.2f", et_bounds[etbin], eta_bounds[etabin]);
1132  }
1133 }
1134 //----------------------------------------------------------------------------------------
1135 unsigned int
1137  const std::string& vars) const
1138 {
1139  unsigned int mask = 0x0;
1140  ATH_MSG_DEBUG("Variables to be used: ");
1141  for (unsigned int var = 0; var < s_fnVariables; var++) {
1142  if (vars.find(s_fVariables[var]) != std::string::npos) {
1143  ATH_MSG_DEBUG(s_fVariables[var]);
1144  mask = mask | 0x1 << var;
1145  }
1146  }
1147  ATH_MSG_DEBUG("mask: " << mask);
1148  return mask;
1149 }
1150 
1151 //----------------------------------------------------------------------------------------
1152 // Note that this will only perform the cut interpolation up to ~45 GeV, so
1153 // no smoothing is done above this for the high ET LH binning yet
1154 double
1156  const std::vector<double>& cuts,
1157  const std::vector<double>& cuts_4gev,
1158  double et,
1159  double eta) const
1160 {
1161 
1162 
1163  //get the value of the cut
1164  unsigned int etbinLH = getLikelihoodEtDiscBin(et, true);
1165  unsigned int etabin = getLikelihoodEtaBin(eta);
1166  unsigned int ibin_combinedLH = etbinLH * s_fnEtaBins + etabin;
1167  double cut = cuts.at(ibin_combinedLH);
1168 
1169  //Special low pt cuts
1170  if (!cuts_4gev.empty()) {
1171  if (et < 7000.) {
1172  cut = cuts_4gev.at(etabin);
1173  }
1174  // Below 6 GeV we do not interpolate
1175  if (et < 6000) {
1176  return cut;
1177  }
1178  } else {// No special low Et cuts
1179  // and below 8500 we do not interpolate
1180  if (et < 8500.) {
1181  return cut;
1182  }
1183  }
1184  // We interpolate until 47500 (last bin)
1185  // size of array is s_fnDiscEtBins
1186  if (et > 47500. || !(etbinLH < s_fnDiscEtBins)) {
1187  return cut;
1188  }
1189  // Interpolate
1190  double bin_width = 5000.;
1191  if (7000. < et && et < 10000.) {
1192  bin_width = 3000.;
1193  }
1194  if (et < 7000.) {
1195  bin_width = 2000.;
1196  }
1197  const double GeV = 1000;
1198  const double eTBins[s_fnDiscEtBins] = { 8.5 * GeV, 12.5 * GeV, 17.5 * GeV,
1199  22.5 * GeV, 27.5 * GeV, 32.5 * GeV,
1200  37.5 * GeV, 42.5 * GeV, 47.5 * GeV };
1201  double bin_center = eTBins[etbinLH];
1202  if (et > bin_center) {
1203  double cut_next = cut;
1204  if (etbinLH + 1 <= 8)
1205  cut_next = cuts.at((etbinLH + 1) * s_fnEtaBins + etabin);
1206  return cut + (cut_next - cut) * (et - bin_center) / (bin_width);
1207  }
1208  // or else if et < bin_center :
1209  double cut_before = cut;
1210  if (etbinLH >= 1) {
1211  cut_before = cuts.at((etbinLH - 1) * s_fnEtaBins + etabin);
1212  } else if (etbinLH == 0 && !cuts_4gev.empty()) {
1213  cut_before = cuts_4gev.at(etabin);
1214  }
1215 
1216  return cut - (cut - cut_before) * (bin_center - et) / (bin_width);
1217 }
1218 
1219 //----------------------------------------------------------------------------------------
1220 // Note that this will only perform the PDF interpolation up to ~45 GeV, so
1221 // no smoothing is done above this for the high ET LH binning yet
1222 double
1224  unsigned int ipbin,
1225  double et,
1226  double eta,
1227  int bin,
1228  unsigned int var) const
1229 {
1230  // histograms exist for the following bins: 4, 7, 10, 15, 20, 30, 40.
1231  // Interpolation between histograms must follow fairly closely the
1232  // interpolation scheme between cuts - so be careful!
1233  int etbin = getLikelihoodEtHistBin(et); // hist binning
1234  int etabin = getLikelihoodEtaBin(eta);
1235  double integral =
1236  double(fPDFbins[s_or_b][ipbin][etbin][etabin][var]->Integral());
1237  double prob =
1238  double(fPDFbins[s_or_b][ipbin][etbin][etabin][var]->GetBinContent(bin)) /
1239  integral;
1240 
1241  int Nbins = fPDFbins[s_or_b][ipbin][etbin][etabin][var]->GetNbinsX();
1242  if (et > 42500.) {
1243  return prob; // interpolation stops here.
1244  }
1245  if (et < 6000.) {
1246  return prob; // interpolation stops here.
1247  }
1248  if (22500. < et && et < 27500.) {
1249  return prob; // region of non-interpolation for pdfs
1250  }
1251  if (32500. < et && et < 37500.) {
1252  return prob; // region of non-interpolation for pdfs
1253  }
1254  double bin_width = 5000.;
1255  if (7000. < et && et < 10000.) {
1256  bin_width = 3000.;
1257  }
1258  if (et < 7000.) {
1259  bin_width = 2000.;
1260  }
1261  const double GeV = 1000;
1262  const double eTHistBins[s_fnEtBinsHist] = { 6. * GeV, 8.5 * GeV,
1263  12.5 * GeV, 17.5 * GeV,
1264  22.5 * GeV, 32.5 * GeV,
1265  42.5 * GeV };
1266  double bin_center = eTHistBins[etbin];
1267  if (etbin == 4 && et >= 27500.) {
1268  bin_center = 27500.; // special: interpolate starting from 27.5 here
1269  }
1270  if (etbin == 5 && et >= 37500.) {
1271  bin_center = 37500.; // special: interpolate starting from 37.5 here
1272  }
1273  if (et > bin_center) {
1274  double prob_next = prob;
1275  if (etbin + 1 <= 6) {
1276  // account for potential histogram bin inequalities
1277  int NbinsPlus =
1278  fPDFbins[s_or_b][ipbin][etbin + 1][etabin][var]->GetNbinsX();
1279  int binplus = bin;
1280  if (Nbins < NbinsPlus) {
1281  binplus = int(round(bin * (Nbins / NbinsPlus)));
1282  } else if (Nbins > NbinsPlus) {
1283  binplus = int(round(bin * (NbinsPlus / Nbins)));
1284  }
1285  // do interpolation
1286  double integral_next =
1287  double(fPDFbins[s_or_b][ipbin][etbin + 1][etabin][var]->Integral());
1288  prob_next =
1289  double(fPDFbins[s_or_b][ipbin][etbin + 1][etabin][var]->GetBinContent(
1290  binplus)) /
1291  integral_next;
1292  return prob + (prob_next - prob) * (et - bin_center) / (bin_width);
1293  }
1294  }
1295  // or else if et < bin_center :
1296  double prob_before = prob;
1297  if (etbin - 1 >= 0) {
1298  // account for potential histogram bin inequalities
1299  int NbinsMinus =
1300  fPDFbins[s_or_b][ipbin][etbin - 1][etabin][var]->GetNbinsX();
1301  int binminus = bin;
1302  if (Nbins < NbinsMinus) {
1303  binminus = int(round(bin * (Nbins / NbinsMinus)));
1304  } else if (Nbins > NbinsMinus) {
1305  binminus = int(round(bin * (NbinsMinus / Nbins)));
1306  }
1307  double integral_before =
1308  double(fPDFbins[s_or_b][ipbin][etbin - 1][etabin][var]->Integral());
1309  prob_before =
1310  double(fPDFbins[s_or_b][ipbin][etbin - 1][etabin][var]->GetBinContent(
1311  binminus)) /
1312  integral_before;
1313  }
1314  return prob - (prob - prob_before) * (bin_center - et) / (bin_width);
1315 }
1316 
1317 //----------------------------------------------------------------------------------------
1318 
1319 // These are the variables availalble in the likelihood.
1320 const std::string Root::TElectronLikelihoodTool::s_fVariables[s_fnVariables] = {
1321  "el_d0significance",
1322  "el_eratio",
1323  "el_deltaeta1",
1324  "el_f1",
1325  "el_f3",
1326  "el_reta",
1327  "el_rhad",
1328  "el_rphi",
1329  "el_trackd0pvunbiased",
1330  "el_weta2",
1331  "el_DeltaPoverP",
1332  "el_deltaphiRescaled",
1333  "el_TRT_PID"
1334 };
LikeEnum::LHCalcVars_t::d0
double d0
Definition: TElectronLikelihoodTool.h:67
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
LikeEnum::LHAcceptVars_t::nPixHitsPlusDeadSensors
int nPixHitsPlusDeadSensors
Definition: TElectronLikelihoodTool.h:44
Root::EGSelectors::SafeTH1
Definition: SafeTH1.h:12
beamspotnt.var
var
Definition: bin/beamspotnt.py:1394
ElectronSelectorHelpers::passAmbiguity
bool passAmbiguity(xAOD::AmbiguityTool::AmbiguityType type, const uint16_t criterion)
return true if the ambiguity type is one of several that are stored in a bitmask
Definition: ElectronSelectorHelpers.cxx:104
xAOD::eratio
setCharge setNTRTHiThresholdHits eratio
Definition: TrigElectron_v1.cxx:96
LikeEnum::LHAcceptVars_t::eT
double eT
Definition: TElectronLikelihoodTool.h:42
et
Extra patterns decribing particle interation process.
GeV
#define GeV
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.cxx:17
LikeEnum::LHAcceptVars_t
Definition: TElectronLikelihoodTool.h:39
get_generator_info.result
result
Definition: get_generator_info.py:21
LikeEnum::LHAcceptVars_t::ambiguityBit
uint8_t ambiguityBit
Definition: TElectronLikelihoodTool.h:46
Root::TElectronLikelihoodTool::getBinName
static void getBinName(char *buffer, int etbin, int etabin, int ipbin, const std::string &iptype)
Definition: TElectronLikelihoodTool.cxx:1114
Root::TElectronLikelihoodTool::TElectronLikelihoodTool
TElectronLikelihoodTool(const char *name="TElectronLikelihoodTool")
Standard constructor.
Definition: TElectronLikelihoodTool.cxx:28
TElectronLikelihoodTool.h
Root::TElectronLikelihoodTool::getIpBin
static unsigned int getIpBin(double ip)
Definition: TElectronLikelihoodTool.cxx:1027
LikeEnum::LHCalcVars_t::Reta
double Reta
Definition: TElectronLikelihoodTool.h:62
keylayer_zslicemap.pb
pb
Definition: keylayer_zslicemap.py:188
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
TCS::KFMET::nEtaBins
constexpr unsigned nEtaBins
Definition: KalmanMETCorrectionConstants.h:18
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:557
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
integral
double integral(TH1 *h)
Definition: computils.cxx:57
xAOD::EgammaParameters::Reta
@ Reta
e237/e277
Definition: EgammaEnums.h:154
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
xAOD::et
et
Definition: TrigEMCluster_v1.cxx:25
LikeEnum::LHCalcVars_t::rHad1
double rHad1
Definition: TElectronLikelihoodTool.h:61
Root::TElectronLikelihoodTool::getLikelihoodEtHistBin
static unsigned int getLikelihoodEtHistBin(double eT)
Coarse Et binning. Used for the likelihood pdfs.
Definition: TElectronLikelihoodTool.cxx:1055
CheckAppliedSFs.bin_width
bin_width
Definition: CheckAppliedSFs.py:242
plotmaker.hist
hist
Definition: plotmaker.py:148
CutsMETMaker::accept
StatusCode accept(const xAOD::Muon *mu)
Definition: CutsMETMaker.cxx:18
ConvertOldUJHistosToNewHistos.etaBins
list etaBins
Definition: ConvertOldUJHistosToNewHistos.py:145
Root::TElectronLikelihoodTool::s_fnEtaBins
static constexpr unsigned int s_fnEtaBins
Definition: TElectronLikelihoodTool.h:336
MuonGM::round
float round(const float toRound, const unsigned int decimals)
Definition: Mdt.cxx:27
LikeEnum::LHCalcVars_t::TRT_PID
double TRT_PID
Definition: TElectronLikelihoodTool.h:72
asg
Definition: DataHandleTestTool.h:28
bin
Definition: BinsDiffFromStripMedian.h:43
LikeEnum::LHCalcVars_t::d0sigma
double d0sigma
Definition: TElectronLikelihoodTool.h:68
Root::TElectronLikelihoodTool::initialize
StatusCode initialize()
Initialize this class.
Definition: TElectronLikelihoodTool.cxx:91
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:12
Root::TElectronLikelihoodTool::~TElectronLikelihoodTool
~TElectronLikelihoodTool()
Standard destructor.
Definition: TElectronLikelihoodTool.cxx:72
xAOD::wstot
setEt setPhi setE277 setWeta2 setEta1 setE2tsts1 wstot
Definition: TrigEMCluster_v1.cxx:49
covarianceTool.prob
prob
Definition: covarianceTool.py:678
Root::TElectronLikelihoodTool::calculate
double calculate(LikeEnum::LHCalcVars_t &vars_struct) const
Definition: TElectronLikelihoodTool.cxx:724
ElectronSelectorHelpers::passBLayerRequirement
bool passBLayerRequirement(const xAOD::TrackParticle &tp)
return true if effective number of BL hits + outliers is at least one
Definition: ElectronSelectorHelpers.cxx:59
LikeEnum::LHAcceptVars_t::ip
double ip
Definition: TElectronLikelihoodTool.h:52
Root::TElectronLikelihoodTool::s_fnEtBinsHist
static constexpr unsigned int s_fnEtBinsHist
Definition: TElectronLikelihoodTool.h:329
python.utils.AtlRunQueryLookup.mask
string mask
Definition: AtlRunQueryLookup.py:460
LikeEnum::LHCalcVars_t
Definition: TElectronLikelihoodTool.h:56
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
LikeEnum::LHCalcVars_t::ip
double ip
Definition: TElectronLikelihoodTool.h:73
xAOD::EgammaParameters::f3
@ f3
fraction of energy reconstructed in 3rd sampling
Definition: EgammaEnums.h:54
CxxUtils::vec
typename vecDetail::vec_typedef< T, N >::type vec
Define a nice alias for the vectorized type.
Definition: vec.h:207
Root::TElectronLikelihoodTool::accept
asg::AcceptData accept() const
Return dummy accept with only info.
Definition: TElectronLikelihoodTool.h:113
ElectronSelectorHelpers.h
Root::TElectronLikelihoodTool::s_fnVariables
static constexpr unsigned int s_fnVariables
Definition: TElectronLikelihoodTool.h:337
xAOD::etaBin
setSAddress setEtaMS setDirPhiMS setDirZMS setBarrelRadius setEndcapAlpha setEndcapRadius setInterceptInner setEtaMap etaBin
Definition: L2StandAloneMuon_v1.cxx:148
createCoolChannelIdFile.buffer
buffer
Definition: createCoolChannelIdFile.py:12
Root::TElectronLikelihoodTool::InterpolateCuts
double InterpolateCuts(const std::vector< double > &cuts, const std::vector< double > &cuts_4gev, double et, double eta) const
Definition: TElectronLikelihoodTool.cxx:1155
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
LikeEnum::LHAcceptVars_t::deltaEta
double deltaEta
Definition: TElectronLikelihoodTool.h:48
LikeEnum::LHCalcVars_t::eT
double eT
Definition: TElectronLikelihoodTool.h:58
LikeEnum::LHCalcVars_t::deltaphires
double deltaphires
Definition: TElectronLikelihoodTool.h:71
IDTPM::eT
float eT(const U &p)
Accessor utility function for getting the value of Tranverse energy.
Definition: TrackParametersHelper.h:120
P4Helpers::deltaEta
double deltaEta(const I4Momentum &p1, const I4Momentum &p2)
Computes efficiently .
Definition: P4Helpers.h:66
LikeEnum::LHCalcVars_t::f3
double f3
Definition: TElectronLikelihoodTool.h:59
LikeEnum::LHAcceptVars_t::wstot
double wstot
Definition: TElectronLikelihoodTool.h:50
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
LikeEnum::LHCalcVars_t::eratio
double eratio
Definition: TElectronLikelihoodTool.h:65
AllowedVariables::d0significance
@ d0significance
Definition: AsgElectronSelectorTool.cxx:50
TRT::Track::d0
@ d0
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:62
BindingsTest.cut
cut
This script demonstrates how to call a C++ class from Python Also how to use PyROOT is shown.
Definition: BindingsTest.py:13
plotBeamSpotVert.cuts
string cuts
Definition: plotBeamSpotVert.py:93
find_tgc_unfilled_channelids.ip
ip
Definition: find_tgc_unfilled_channelids.py:3
LikeEnum::LHAcceptVars_t::likelihood
double likelihood
Definition: TElectronLikelihoodTool.h:40
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
xAOD::AmbiguityTool::AmbiguityType
AmbiguityType
Definition: IEGammaAmbiguityTool.h:33
LikeEnum::LHAcceptVars_t::passBLayerRequirement
bool passBLayerRequirement
Definition: TElectronLikelihoodTool.h:45
compute_lumi.denom
denom
Definition: compute_lumi.py:76
Root::TElectronLikelihoodTool::fPDFbins
EGSelectors::SafeTH1 * fPDFbins[2][IP_BINS][s_fnEtBinsHist][s_fnEtaBins][s_fnVariables]
Definition: TElectronLikelihoodTool.h:340
Root::TElectronLikelihoodTool::s_fVariables
static const std::string s_fVariables[s_fnVariables]
Definition: TElectronLikelihoodTool.h:341
min
#define min(a, b)
Definition: cfImp.cxx:40
LikeEnum::LHCalcVars_t::rphi
double rphi
Definition: TElectronLikelihoodTool.h:69
EMFourMomBuilder::calculate
void calculate(xAOD::Electron &electron)
Definition: EMFourMomBuilder.cxx:68
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
plotBeamSpotVxVal.bin
int bin
Definition: plotBeamSpotVxVal.py:83
LikeEnum::LHCalcVars_t::eta
double eta
Definition: TElectronLikelihoodTool.h:57
LikeEnum::LHAcceptVars_t::nSiHitsPlusDeadSensors
int nSiHitsPlusDeadSensors
Definition: TElectronLikelihoodTool.h:43
Root::TElectronLikelihoodTool::evaluateLikelihood
double evaluateLikelihood(const std::vector< double > &varVector, double et, double eta, double ip=0) const
Definition: TElectronLikelihoodTool.cxx:770
python.AthDsoLogger.fname
string fname
Definition: AthDsoLogger.py:67
LikeEnum::LHCalcVars_t::rHad
double rHad
Definition: TElectronLikelihoodTool.h:60
asg::AcceptData::setCutResult
void setCutResult(const std::string &cutName, bool cutResult)
Set the result of a cut, based on the cut name (safer)
Definition: AcceptData.h:134
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
AllowedVariables::nPixHitsPlusDeadSensors
@ nPixHitsPlusDeadSensors
Definition: AsgElectronSelectorTool.cxx:57
Root::TElectronLikelihoodTool::getLikelihoodBitmask
unsigned int getLikelihoodBitmask(const std::string &vars) const
Definition: TElectronLikelihoodTool.cxx:1136
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
Root::TElectronLikelihoodTool::TransformLikelihoodOutput
double TransformLikelihoodOutput(double ps, double pb, double ip, double et, double eta) const
Apply a transform to zoom into the LH output peaks.
Definition: TElectronLikelihoodTool.cxx:868
PowhegPythia8EvtGen_jetjet.pdf
pdf
Definition: PowhegPythia8EvtGen_jetjet.py:4
Root::TElectronLikelihoodTool::InterpolatePdfs
double InterpolatePdfs(unsigned int s_or_b, unsigned int ipbin, double et, double eta, int bin, unsigned int var) const
Definition: TElectronLikelihoodTool.cxx:1223
LikeEnum::LHAcceptVars_t::EoverP
double EoverP
Definition: TElectronLikelihoodTool.h:51
LikeEnum::LHAcceptVars_t::d0
double d0
Definition: TElectronLikelihoodTool.h:47
Root::TElectronLikelihoodTool::loadVarHistograms
int loadVarHistograms(const std::string &vstr, TFile *pdfFile, unsigned int varIndex)
Load the variable histograms from the pdf file.
Definition: TElectronLikelihoodTool.cxx:349
LikeEnum::LHCalcVars_t::f1
double f1
Definition: TElectronLikelihoodTool.h:64
LikeEnum::LHAcceptVars_t::eta
double eta
Definition: TElectronLikelihoodTool.h:41
AllowedVariables::EoverP
@ EoverP
Definition: AsgElectronSelectorTool.cxx:56
python.TrigEgammaMonitorHelper.TH1F
def TH1F(name, title, nxbins, bins_par2, bins_par3=None, path='', **kwargs)
Definition: TrigEgammaMonitorHelper.py:24
Root::TElectronLikelihoodTool::getLikelihoodEtaBin
static unsigned int getLikelihoodEtaBin(double eta)
Eta binning for pdfs and discriminant cuts.
Definition: TElectronLikelihoodTool.cxx:1039
LikeEnum::LHCalcVars_t::deltaEta
double deltaEta
Definition: TElectronLikelihoodTool.h:66
LikeEnum::LHCalcVars_t::w2
double w2
Definition: TElectronLikelihoodTool.h:63
LikeEnum::LHCalcVars_t::deltaPoverP
double deltaPoverP
Definition: TElectronLikelihoodTool.h:70
asg::AcceptData
Definition: AcceptData.h:30
LikeEnum::LHAcceptVars_t::deltaphires
double deltaphires
Definition: TElectronLikelihoodTool.h:49
Root::TElectronLikelihoodTool::getLikelihoodEtDiscBin
unsigned int getLikelihoodEtDiscBin(double eT, const bool isLHbinning) const
Fine Et binning. Used for the likelihood discriminant cuts.
Definition: TElectronLikelihoodTool.cxx:1075
read_hist_ntuple.f1
f1
Definition: read_hist_ntuple.py:4