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