Loading [MathJax]/jax/input/TeX/config.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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  fPDFbins[s_or_b][ip][et][eta][varIndex] =
387  delete hist;
388  } else {
389  ATH_MSG_INFO("Warning: Object " << pdf << " does not exist.");
390  ATH_MSG_INFO("Skipping all other histograms with this variable.");
391  return 1;
392  }
393  }
394  }
395  }
396  }
397  return 1;
398 }
399 
402  double eta,
403  double eT,
404  int nSiHitsPlusDeadSensors,
407  uint8_t ambiguityBit,
408  double d0,
409  double deltaEta,
410  double deltaphires,
411  double wstot,
412  double EoverP,
413  double ip) const
414 {
416  vars.likelihood = likelihood;
417  vars.eta = eta;
418  vars.eT = eT;
419  vars.nSiHitsPlusDeadSensors = nSiHitsPlusDeadSensors;
420  vars.nPixHitsPlusDeadSensors = nPixHitsPlusDeadSensors;
421  vars.passBLayerRequirement = passBLayerRequirement;
422  vars.ambiguityBit = ambiguityBit;
423  vars.d0 = d0;
424  vars.deltaEta = deltaEta;
425  vars.deltaphires = deltaphires;
426  vars.wstot = wstot;
427  vars.EoverP = EoverP;
428  vars.ip = ip;
429 
430  return accept(vars);
431 }
432 
433 // This method calculates if the current electron passes the requested
434 // likelihood cut
437  LikeEnum::LHAcceptVars_t& vars_struct) const
438 {
439  // Setup return accept with AcceptInfo
440  asg::AcceptData acceptData(&m_acceptInfo);
441 
442  // Set up the individual cuts
443  bool passKine(true);
444  bool passNSilicon(true);
445  bool passNPixel(true);
446  bool passNBlayer(true);
447  bool passAmbiguity(true);
448  bool passLH(true);
449  bool passTrackA0(true);
450  bool passDeltaEta(true);
451  bool passDeltaPhiRes(true);
452  bool passWstotAtHighET(true);
453  bool passEoverPAtHighET(true);
454 
455  if (std::abs(vars_struct.eta) > 2.47) {
456  ATH_MSG_DEBUG("This electron is std::abs(eta)>2.47 Returning False.");
457  passKine = false;
458  }
459 
460  unsigned int etbinLH = getLikelihoodEtDiscBin(vars_struct.eT, true);
461  unsigned int etbinOther = getLikelihoodEtDiscBin(vars_struct.eT, false);
462  unsigned int etabin = getLikelihoodEtaBin(vars_struct.eta);
463 
464  // sanity
465  if (etbinLH >= s_fnDiscEtBinsOneExtra) {
466  ATH_MSG_WARNING("Cannot evaluate likelihood for Et "
467  << vars_struct.eT << ". Returning false..");
468  passKine = false;
469  }
470  // sanity
471  if (etbinOther >= s_fnDiscEtBins) {
472  ATH_MSG_WARNING("Cannot evaluate likelihood for Et "
473  << vars_struct.eT << ". Returning false..");
474  passKine = false;
475  }
476 
477  // Return if the kinematic requirements are not fulfilled
478  acceptData.setCutResult(m_cutPosition_kinematic, passKine);
479  if (!passKine) {
480  return acceptData;
481  }
482 
483  // ambiguity bit
484  if (!m_cutAmbiguity.empty()) {
487  m_cutAmbiguity[etabin])) {
488  ATH_MSG_DEBUG("Likelihood macro: ambiguity Bit Failed.");
489  passAmbiguity = false;
490  }
491  }
492 
493  // blayer cut
494  if (!m_cutBL.empty()) {
495  if (m_cutBL[etabin] == 1 && !vars_struct.passBLayerRequirement) {
496  ATH_MSG_DEBUG("Likelihood macro: Blayer cut failed.");
497  passNBlayer = false;
498  }
499  }
500  // pixel cut
501  if (!m_cutPi.empty()) {
502  if (vars_struct.nPixHitsPlusDeadSensors < m_cutPi[etabin]) {
503  ATH_MSG_DEBUG("Likelihood macro: Pixels Failed.");
504  passNPixel = false;
505  }
506  }
507  // silicon cut
508  if (!m_cutSi.empty()) {
509  if (vars_struct.nSiHitsPlusDeadSensors < m_cutSi[etabin]) {
510  ATH_MSG_DEBUG("Likelihood macro: Silicon Failed.");
511  passNSilicon = false;
512  }
513  }
514 
515  double cutDiscriminant;
516  unsigned int ibin_combinedLH =
517  etbinLH * s_fnEtaBins + etabin; // Must change if number of eta bins
518  // changes!. Also starts from 7-10 GeV bin.
519  unsigned int ibin_combinedOther =
520  etbinOther * s_fnEtaBins +
521  etabin; // Must change if number of eta bins changes!. Also
522  // starts from 7-10 GeV bin.
523 
524  if (!m_cutLikelihood.empty()) {
525  // To protect against a binning mismatch, which should never happen
526  if (ibin_combinedLH >= m_cutLikelihood.size()) {
527  ATH_MSG_ERROR("The desired eta/pt bin "
528  << ibin_combinedLH
529  << " is outside of the range specified by the input"
530  << m_cutLikelihood.size() << "This should never happen!");
531  return acceptData;
532  }
533 
534  if (m_doSmoothBinInterpolation) {
535  cutDiscriminant = InterpolateCuts(
536  m_cutLikelihood, m_cutLikelihood4GeV, vars_struct.eT, vars_struct.eta);
537  if (!m_doPileupTransform && !m_cutLikelihoodPileupCorrection.empty() &&
538  !m_cutLikelihoodPileupCorrection4GeV.empty())
539  cutDiscriminant +=
540  vars_struct.ip * InterpolateCuts(m_cutLikelihoodPileupCorrection,
541  m_cutLikelihoodPileupCorrection4GeV,
542  vars_struct.eT,
543  vars_struct.eta);
544  } else {
545  if (vars_struct.eT > 7000. || m_cutLikelihood4GeV.empty()) {
546  cutDiscriminant = m_cutLikelihood[ibin_combinedLH];
547  // If doPileupTransform, then correct the discriminant itself instead of
548  // the cut value
549  if (!m_doPileupTransform && !m_cutLikelihoodPileupCorrection.empty()) {
550  cutDiscriminant +=
551  vars_struct.ip * m_cutLikelihoodPileupCorrection[ibin_combinedLH];
552  }
553  } else {
554  cutDiscriminant = m_cutLikelihood4GeV[etabin];
555  if (!m_doPileupTransform &&
556  !m_cutLikelihoodPileupCorrection4GeV.empty())
557  cutDiscriminant +=
558  vars_struct.ip * m_cutLikelihoodPileupCorrection4GeV[etabin];
559  }
560  }
561 
562  // Determine if the calculated likelihood value passes the cut
563  ATH_MSG_DEBUG("Likelihood macro: Discriminant: ");
564  if (vars_struct.likelihood < cutDiscriminant) {
565  ATH_MSG_DEBUG("Likelihood macro: Disciminant Cut Failed.");
566  passLH = false;
567  }
568  }
569 
570  // d0 cut
571  if (!m_cutA0.empty()) {
572  if (std::abs(vars_struct.d0) > m_cutA0[ibin_combinedOther]) {
573  ATH_MSG_DEBUG("Likelihood macro: D0 Failed.");
574  passTrackA0 = false;
575  }
576  }
577 
578  // deltaEta cut
579  if (!m_cutDeltaEta.empty()) {
580  if (std::abs(vars_struct.deltaEta) > m_cutDeltaEta[ibin_combinedOther]) {
581  ATH_MSG_DEBUG("Likelihood macro: deltaEta Failed.");
582  passDeltaEta = false;
583  }
584  }
585 
586  // deltaPhiRes cut
587  if (!m_cutDeltaPhiRes.empty()) {
588  if (std::abs(vars_struct.deltaphires) >
589  m_cutDeltaPhiRes[ibin_combinedOther]) {
590  ATH_MSG_DEBUG("Likelihood macro: deltaphires Failed.");
591  passDeltaPhiRes = false;
592  }
593  }
594 
595  // Only do this above HighETBinThreshold [in GeV]
596  if (vars_struct.eT > m_highETBinThreshold * 1000) {
597  // wstot cut
598  if (!m_cutWstotAtHighET.empty()) {
599  if (std::abs(vars_struct.wstot) > m_cutWstotAtHighET[etabin]) {
600  ATH_MSG_DEBUG("Likelihood macro: wstot Failed.");
601  passWstotAtHighET = false;
602  }
603  }
604 
605  // EoverP cut
606  if (!m_cutEoverPAtHighET.empty()) {
607  if (std::abs(vars_struct.EoverP) > m_cutEoverPAtHighET[etabin]) {
608  ATH_MSG_DEBUG("Likelihood macro: EoverP Failed.");
609  passEoverPAtHighET = false;
610  }
611  }
612  }
613 
614  // Set the individual cut bits in the return object
615  acceptData.setCutResult(m_cutPosition_NSilicon, passNSilicon);
616  acceptData.setCutResult(m_cutPosition_NPixel, passNPixel);
617  acceptData.setCutResult(m_cutPosition_NBlayer, passNBlayer);
618  acceptData.setCutResult(m_cutPosition_ambiguity, passAmbiguity);
619  acceptData.setCutResult(m_cutPosition_LH, passLH);
620  acceptData.setCutResult(m_cutPositionTrackA0, passTrackA0);
621  acceptData.setCutResult(m_cutPositionTrackMatchEta, passDeltaEta);
622  acceptData.setCutResult(m_cutPositionTrackMatchPhiRes, passDeltaPhiRes);
623  acceptData.setCutResult(m_cutPositionWstotAtHighET, passWstotAtHighET);
624  acceptData.setCutResult(m_cutPositionEoverPAtHighET, passEoverPAtHighET);
625  return acceptData;
626 }
627 
628 double
630  double eT,
631  double f3,
632  double rHad,
633  double rHad1,
634  double Reta,
635  double w2,
636  double f1,
637  double eratio,
638  double deltaEta,
639  double d0,
640  double d0sigma,
641  double rphi,
642  double deltaPoverP,
643  double deltaphires,
644  double TRT_PID,
645  double ip) const
646 {
647 
648  LikeEnum::LHCalcVars_t vars{};
649 
650  vars.eta = eta;
651  vars.eT = eT;
652  vars.f3 = f3;
653  vars.rHad = rHad;
654  vars.rHad1 = rHad1;
655  vars.Reta = Reta;
656  vars.w2 = w2;
657  vars.f1 = f1;
658  vars.eratio = eratio;
659  vars.deltaEta = deltaEta;
660  vars.d0 = d0;
661  vars.d0sigma = d0sigma;
662  vars.rphi = rphi;
663  vars.deltaPoverP = deltaPoverP;
664  vars.deltaphires = deltaphires;
665  vars.TRT_PID = TRT_PID;
666  vars.ip = ip;
667 
668  return calculate(vars);
669 }
670 
671 // The main public method to actually calculate the likelihood value
672 double
674  LikeEnum::LHCalcVars_t& vars_struct) const
675 {
676  // Reset the results to defaul values
677  double result = -999;
678 
679  unsigned int etabin = getLikelihoodEtaBin(vars_struct.eta);
680  double rhad_corr;
681  if (etabin == 3 || etabin == 4) {
682  rhad_corr = vars_struct.rHad;
683  } else {
684  rhad_corr = vars_struct.rHad1;
685  }
686  double d0significance = vars_struct.d0sigma == 0
687  ? 0.
688  : std::abs(vars_struct.d0) / vars_struct.d0sigma;
689 
690  std::vector<double> vec = {
691  d0significance, vars_struct.eratio, vars_struct.deltaEta,
692  vars_struct.f1, vars_struct.f3, vars_struct.Reta,
693  rhad_corr, vars_struct.rphi, vars_struct.d0,
694  vars_struct.w2, vars_struct.deltaPoverP, vars_struct.deltaphires,
695  vars_struct.TRT_PID
696  };
697  // Calculate the actual likelihood value and fill the return object
698  result = this->evaluateLikelihood(
699  vec, vars_struct.eT, vars_struct.eta, vars_struct.ip);
700 
701  return result;
702 }
703 
704 double
706  const std::vector<float>& varVector,
707  double et,
708  double eta,
709  double ip) const
710 {
711  std::vector<double> vec;
712  for (unsigned int var = 0; var < s_fnVariables; var++) {
713  vec.push_back(varVector[var]);
714  }
715  return evaluateLikelihood(vec, et, eta, ip);
716 }
717 
718 double
720  const std::vector<double>& varVector,
721  double et,
722  double eta,
723  double ip) const
724 {
725 
726  const double GeV = 1000;
727  unsigned int etbin = getLikelihoodEtHistBin(et); // hist binning
728  unsigned int etabin = getLikelihoodEtaBin(eta);
729  unsigned int ipbin = getIpBin(ip);
730 
731  ATH_MSG_DEBUG("et: " << et << " eta: " << eta << " etbin: " << etbin
732  << " etabin: " << etabin);
733 
734  if (etbin >= s_fnEtBinsHist) {
735  ATH_MSG_WARNING("skipping etbin " << etbin << ", et " << et);
736  return -999.;
737  }
738  if (etabin >= s_fnEtaBins) {
739  ATH_MSG_WARNING("skipping etabin " << etabin << ", eta " << eta);
740  return -999.;
741  }
742 
743  if (varVector.size() != s_fnVariables) {
744  ATH_MSG_WARNING("Error! Variable vector size mismatch! Check your vector!");
745  }
746 
747  double SigmaS = 1.;
748  double SigmaB = 1.;
749 
750  // define some string constants
751  const std::string TRT_string = "TRT";
752  const std::string el_f3_string = "el_f3";
753  const std::string el_TRT_PID_string = "el_TRT_PID";
754 
755  for (unsigned int var = 0; var < s_fnVariables; var++) {
756 
757  const std::string& varstr = s_fVariables[var];
758 
759  // Skip variables that are masked off (not used) in the likelihood
760  if (!(m_variableBitMask & (0x1 << var))) {
761  continue;
762  }
763  // Don't use TRT for outer eta bins (2.01,2.37)
764  if (((etabin == 8) || (etabin == 9)) &&
765  (varstr.find(TRT_string) != std::string::npos)) {
766  continue;
767  }
768  // Don't use f3 for outer eta bin (2.37)
769  if ((etabin == 9) && (varstr.find(el_f3_string) != std::string::npos)) {
770  continue;
771  }
772  // Don't use f3 for high et (>80 GeV)
773  if (m_doRemoveF3AtHighEt && (et > 80 * GeV) &&
774  (varstr.find(el_f3_string) != std::string::npos)) {
775  continue;
776  }
777  // Don't use TRTPID for high et (>80 GeV)
778  if (m_doRemoveTRTPIDAtHighEt && (et > 80 * GeV) &&
779  (varstr.find(el_TRT_PID_string) != std::string::npos)) {
780  continue;
781  }
782  for (unsigned int s_or_b = 0; s_or_b < 2; s_or_b++) {
783 
784  int bin =
785  fPDFbins[s_or_b][ipbin][etbin][etabin][var]->FindBin(varVector[var]);
786 
787  double prob = 0;
788  if (m_doSmoothBinInterpolation) {
789  prob = InterpolatePdfs(s_or_b, ipbin, et, eta, bin, var);
790  } else {
791  double integral =
792  double(fPDFbins[s_or_b][ipbin][etbin][etabin][var]->Integral());
793  if (integral == 0) {
794  ATH_MSG_WARNING("Error! PDF integral == 0!");
795  return -1.35;
796  }
797 
798  prob =
799  double(
800  fPDFbins[s_or_b][ipbin][etbin][etabin][var]->GetBinContent(bin)) /
801  integral;
802  }
803 
804  if (s_or_b == 0) {
805  SigmaS *= prob;
806  } else if (s_or_b == 1) {
807  SigmaB *= prob;
808  }
809  }
810  }
811 
812  return TransformLikelihoodOutput(SigmaS, SigmaB, ip, et, eta);
813 }
814 
815 // --------------------------------------------
816 double
818  double pb,
819  double ip,
820  double et,
821  double eta) const
822 {
823  // returns transformed or non-transformed output
824  // (Taken mostly from TMVA likelihood code)
825  double fEpsilon = 1e-99;
826  // If both signal and bkg are 0, we want it to fail.
827  if (ps < fEpsilon)
828  ps = 0;
829  if (pb < fEpsilon)
830  pb = fEpsilon;
831  double disc = ps / double(ps + pb);
832 
833  if (disc >= 1.0) {
834  disc = 1. - 1.e-15;
835  } else if (disc <= 0.0) {
836  disc = fEpsilon;
837  }
838 
839  double tau = 15.0;
840  disc = -log(1.0 / disc - 1.0) * (1. / double(tau));
841 
842  // Linearly transform the discriminant as a function of pileup, rather than
843  // the old scheme of changing the cut value based on pileup. This is simpler
844  // for the tuning, as well as ensuring subsets / making discriminants more
845  // transparent. In the HI case, a quadratic centrality transform is applied
846  // instead.
847  if (m_doPileupTransform) {
848 
849  // The variables used by the transform:
850  //
851  // - hard_cut_ref = extremely tight discriminant cut as reference to ensure
852  // pileup correction for looser menus is less than for tighter menus.
853  // - loose_ref = a loose menu with no pileup correction. Any tighter
854  // menu with same inputs will necessarily have pileup dependence built in
855  // - disc_max = max disc value for which pileup correction is desired.
856  // - pileup_max = max nvtx or mu for calculating the transform. Any larger
857  // pileup values will use this maximum value in the transform.
858 
859  if (m_discHardCutForPileupTransform.empty() ||
860  m_discHardCutSlopeForPileupTransform.empty() ||
861  m_discLooseForPileupTransform.empty()) {
863  "Vectors needed for pileup-dependent transform not correctly filled! "
864  "Skipping the transform.");
865  return disc;
866  }
867 
868  if (m_doCentralityTransform &&
869  m_discHardCutQuadForPileupTransform.empty()) {
870  ATH_MSG_WARNING("Vectors needed for centrality-dependent transform not "
871  "correctly filled! "
872  "Skipping the transform.");
873  return disc;
874  }
875 
876  unsigned int etabin = getLikelihoodEtaBin(eta);
877 
878  double disc_hard_cut_ref = 0;
879  double disc_hard_cut_ref_slope = 0;
880  double disc_hard_cut_ref_quad =
881  0; // only used for heavy ion implementation of the LH
882  double disc_loose_ref = 0;
883  double disc_max = m_discMaxForPileupTransform;
884  double pileup_max = m_pileupMaxForPileupTransform;
885 
886  if (m_doSmoothBinInterpolation) {
887  disc_hard_cut_ref = InterpolateCuts(m_discHardCutForPileupTransform,
888  m_discHardCutForPileupTransform4GeV,
889  et,
890  eta);
891  disc_hard_cut_ref_slope =
892  InterpolateCuts(m_discHardCutSlopeForPileupTransform,
893  m_discHardCutSlopeForPileupTransform4GeV,
894  et,
895  eta);
896  if (m_doCentralityTransform)
897  disc_hard_cut_ref_quad =
898  InterpolateCuts(m_discHardCutQuadForPileupTransform,
899  m_discHardCutQuadForPileupTransform4GeV,
900  et,
901  eta);
902  disc_loose_ref = InterpolateCuts(m_discLooseForPileupTransform,
903  m_discLooseForPileupTransform4GeV,
904  et,
905  eta);
906  } else {
907  // default situation, in the case where 4-7 GeV bin is not defined
908  if (et > 7000. || m_discHardCutForPileupTransform4GeV.empty()) {
909  unsigned int etfinebinLH = getLikelihoodEtDiscBin(et, true);
910  unsigned int ibin_combined = etfinebinLH * s_fnEtaBins + etabin;
911  disc_hard_cut_ref = m_discHardCutForPileupTransform[ibin_combined];
912  disc_hard_cut_ref_slope =
913  m_discHardCutSlopeForPileupTransform[ibin_combined];
914  if (m_doCentralityTransform)
915  disc_hard_cut_ref_quad =
916  m_discHardCutQuadForPileupTransform[ibin_combined];
917  disc_loose_ref = m_discLooseForPileupTransform[ibin_combined];
918  } else {
919  if (m_discHardCutForPileupTransform4GeV.empty() ||
920  m_discHardCutSlopeForPileupTransform4GeV.empty() ||
921  m_discLooseForPileupTransform4GeV.empty()) {
922  ATH_MSG_WARNING("Vectors needed for pileup-dependent transform not "
923  "correctly filled for 4-7 GeV "
924  "bin! Skipping the transform.");
925  return disc;
926  }
927  if (m_doCentralityTransform &&
928  m_discHardCutQuadForPileupTransform4GeV.empty()) {
929  ATH_MSG_WARNING("Vectors needed for centrality-dependent transform "
930  "not correctly filled for 4-7 "
931  "GeV bin! Skipping the transform.");
932  return disc;
933  }
934  disc_hard_cut_ref = m_discHardCutForPileupTransform4GeV[etabin];
935  disc_hard_cut_ref_slope =
936  m_discHardCutSlopeForPileupTransform4GeV[etabin];
937  if (m_doCentralityTransform)
938  disc_hard_cut_ref_quad =
939  m_discHardCutQuadForPileupTransform4GeV[etabin];
940  disc_loose_ref = m_discLooseForPileupTransform4GeV[etabin];
941  }
942  }
943 
944  double ip_for_corr =
945  std::min(ip, pileup_max); // turn off correction for values > pileup_max
946  double disc_hard_cut_ref_prime =
947  disc_hard_cut_ref + disc_hard_cut_ref_slope * ip_for_corr +
948  disc_hard_cut_ref_quad * ip_for_corr * ip_for_corr;
949 
950  if (disc <= disc_loose_ref) {
951  // Below threshold for applying pileup correction
952  } else if (disc <= disc_hard_cut_ref_prime) {
953  // Between the loose and hard cut reference points for pileup correction
954  double denom = double(disc_hard_cut_ref_prime - disc_loose_ref);
955  if (denom < 0.001)
956  denom = 0.001;
957  disc = disc_loose_ref + (disc - disc_loose_ref) *
958  (disc_hard_cut_ref - disc_loose_ref) / denom;
959  } else if (disc_hard_cut_ref_prime < disc && disc <= disc_max) {
960  // Between the hard cut and max reference points for pileup correction
961  double denom = double(disc_max - disc_hard_cut_ref_prime);
962  if (denom < 0.001)
963  denom = 0.001;
964  disc = disc_hard_cut_ref + (disc - disc_hard_cut_ref_prime) *
965  (disc_max - disc_hard_cut_ref) / denom;
966  }
967  }
968 
969  ATH_MSG_DEBUG("disc is " << disc);
970  return disc;
971 }
972 
973 //---------------------------------------------------------------------------------------
974 // Gets the IP bin
975 unsigned int
977 {
978  for (unsigned int ipBin = 0; ipBin < IP_BINS; ++ipBin) {
979  if (ip < s_fIpBounds[ipBin + 1])
980  return ipBin;
981  }
982  return 0;
983 }
984 
985 //---------------------------------------------------------------------------------------
986 // Gets the Eta bin [0-9] given the eta
987 unsigned int
989 {
990  const unsigned int nEtaBins = s_fnEtaBins;
991  const double etaBins[nEtaBins] = { 0.1, 0.6, 0.8, 1.15, 1.37,
992  1.52, 1.81, 2.01, 2.37, 2.47 };
993 
994  for (unsigned int etaBin = 0; etaBin < nEtaBins; ++etaBin) {
995  if (std::abs(eta) < etaBins[etaBin])
996  return etaBin;
997  }
998 
999  return 9;
1000 }
1001 //---------------------------------------------------------------------------------------
1002 // Gets the histogram Et bin given the et (MeV) -- corrresponds to fnEtBinsHist
1003 unsigned int
1005 {
1006  const double GeV = 1000;
1007 
1008  const unsigned int nEtBins = s_fnEtBinsHist;
1009  const double eTBins[nEtBins] = { 7 * GeV, 10 * GeV, 15 * GeV, 20 * GeV,
1010  30 * GeV, 40 * GeV, 50 * GeV };
1011 
1012  for (unsigned int eTBin = 0; eTBin < nEtBins; ++eTBin) {
1013  if (eT < eTBins[eTBin]) {
1014  return eTBin;
1015  }
1016  }
1017 
1018  return nEtBins - 1; // Return the last bin if > the last bin.
1019 }
1020 
1021 //---------------------------------------------------------------------------------------
1022 // Gets the Et bin [0-10] given the et (MeV)
1023 unsigned int
1025  double eT,
1026  const bool isLHbinning) const
1027 {
1028  const double GeV = 1000;
1029 
1030  if (m_useOneExtraHighETLHBin && isLHbinning) {
1031  const unsigned int nEtBins = s_fnDiscEtBinsOneExtra;
1032  const double eTBins[nEtBins] = {
1033  10 * GeV, 15 * GeV, 20 * GeV,
1034  25 * GeV, 30 * GeV, 35 * GeV,
1035  40 * GeV, 45 * GeV, m_highETBinThreshold * GeV,
1036  6000 * GeV
1037  };
1038 
1039  for (unsigned int eTBin = 0; eTBin < nEtBins; ++eTBin) {
1040  if (eT < eTBins[eTBin])
1041  return eTBin;
1042  }
1043 
1044  return nEtBins - 1; // Return the last bin if > the last bin.
1045  }
1046 
1047  const unsigned int nEtBins = s_fnDiscEtBins;
1048  const double eTBins[nEtBins] = { 10 * GeV, 15 * GeV, 20 * GeV,
1049  25 * GeV, 30 * GeV, 35 * GeV,
1050  40 * GeV, 45 * GeV, 50 * GeV };
1051 
1052  for (unsigned int eTBin = 0; eTBin < nEtBins; ++eTBin) {
1053  if (eT < eTBins[eTBin])
1054  return eTBin;
1055  }
1056 
1057  return nEtBins - 1; // Return the last bin if > the last bin.
1058 }
1059 
1060 //---------------------------------------------------------------------------------------
1061 // Gets the bin name. Given the HISTOGRAM binning (fnEtBinsHist)
1062 std::string
1064  int etabin,
1065  int ipbin,
1066  const std::string& iptype)
1067 {
1068  const double eta_bounds[9] = { 0.0, 0.6, 0.8, 1.15, 1.37, 1.52, 1.81, 2.01, 2.37 };
1069  const int et_bounds[s_fnEtBinsHist] = { 4, 7, 10, 15, 20, 30, 40 };
1070  if (!iptype.empty()) {
1071  return std::format("{}{}et{:02}eta{:.2f}",
1072  iptype, int(s_fIpBounds[ipbin]),
1073  et_bounds[etbin], eta_bounds[etabin]);
1074  } else {
1075  return std::format("et{}eta{:.2f}",
1076  et_bounds[etbin], eta_bounds[etabin]);
1077  }
1078 }
1079 //----------------------------------------------------------------------------------------
1080 unsigned int
1082  const std::string& vars) const
1083 {
1084  unsigned int mask = 0x0;
1085  ATH_MSG_DEBUG("Variables to be used: ");
1086  for (unsigned int var = 0; var < s_fnVariables; var++) {
1087  if (vars.find(s_fVariables[var]) != std::string::npos) {
1088  ATH_MSG_DEBUG(s_fVariables[var]);
1089  mask = mask | 0x1 << var;
1090  }
1091  }
1092  ATH_MSG_DEBUG("mask: " << mask);
1093  return mask;
1094 }
1095 
1096 //----------------------------------------------------------------------------------------
1097 // Note that this will only perform the cut interpolation up to ~45 GeV, so
1098 // no smoothing is done above this for the high ET LH binning yet
1099 double
1101  const std::vector<double>& cuts,
1102  const std::vector<double>& cuts_4gev,
1103  double et,
1104  double eta) const
1105 {
1106 
1107 
1108  //get the value of the cut
1109  unsigned int etbinLH = getLikelihoodEtDiscBin(et, true);
1110  unsigned int etabin = getLikelihoodEtaBin(eta);
1111  unsigned int ibin_combinedLH = etbinLH * s_fnEtaBins + etabin;
1112  double cut = cuts.at(ibin_combinedLH);
1113 
1114  //Special low pt cuts
1115  if (!cuts_4gev.empty()) {
1116  if (et < 7000.) {
1117  cut = cuts_4gev.at(etabin);
1118  }
1119  // Below 6 GeV we do not interpolate
1120  if (et < 6000) {
1121  return cut;
1122  }
1123  } else {// No special low Et cuts
1124  // and below 8500 we do not interpolate
1125  if (et < 8500.) {
1126  return cut;
1127  }
1128  }
1129  // We interpolate until 47500 (last bin)
1130  // size of array is s_fnDiscEtBins
1131  if (et > 47500. || !(etbinLH < s_fnDiscEtBins)) {
1132  return cut;
1133  }
1134  // Interpolate
1135  double bin_width = 5000.;
1136  if (7000. < et && et < 10000.) {
1137  bin_width = 3000.;
1138  }
1139  if (et < 7000.) {
1140  bin_width = 2000.;
1141  }
1142  const double GeV = 1000;
1143  const double eTBins[s_fnDiscEtBins] = { 8.5 * GeV, 12.5 * GeV, 17.5 * GeV,
1144  22.5 * GeV, 27.5 * GeV, 32.5 * GeV,
1145  37.5 * GeV, 42.5 * GeV, 47.5 * GeV };
1146  double bin_center = eTBins[etbinLH];
1147  if (et > bin_center) {
1148  double cut_next = cut;
1149  if (etbinLH + 1 <= 8)
1150  cut_next = cuts.at((etbinLH + 1) * s_fnEtaBins + etabin);
1151  return cut + (cut_next - cut) * (et - bin_center) / (bin_width);
1152  }
1153  // or else if et < bin_center :
1154  double cut_before = cut;
1155  if (etbinLH >= 1) {
1156  cut_before = cuts.at((etbinLH - 1) * s_fnEtaBins + etabin);
1157  } else if (etbinLH == 0 && !cuts_4gev.empty()) {
1158  cut_before = cuts_4gev.at(etabin);
1159  }
1160 
1161  return cut - (cut - cut_before) * (bin_center - et) / (bin_width);
1162 }
1163 
1164 //----------------------------------------------------------------------------------------
1165 // Note that this will only perform the PDF interpolation up to ~45 GeV, so
1166 // no smoothing is done above this for the high ET LH binning yet
1167 double
1169  unsigned int ipbin,
1170  double et,
1171  double eta,
1172  int bin,
1173  unsigned int var) const
1174 {
1175  // histograms exist for the following bins: 4, 7, 10, 15, 20, 30, 40.
1176  // Interpolation between histograms must follow fairly closely the
1177  // interpolation scheme between cuts - so be careful!
1178  int etbin = getLikelihoodEtHistBin(et); // hist binning
1179  int etabin = getLikelihoodEtaBin(eta);
1180  double integral =
1181  double(fPDFbins[s_or_b][ipbin][etbin][etabin][var]->Integral());
1182  double prob =
1183  double(fPDFbins[s_or_b][ipbin][etbin][etabin][var]->GetBinContent(bin)) /
1184  integral;
1185 
1186  int Nbins = fPDFbins[s_or_b][ipbin][etbin][etabin][var]->GetNbinsX();
1187  if (et > 42500.) {
1188  return prob; // interpolation stops here.
1189  }
1190  if (et < 6000.) {
1191  return prob; // interpolation stops here.
1192  }
1193  if (22500. < et && et < 27500.) {
1194  return prob; // region of non-interpolation for pdfs
1195  }
1196  if (32500. < et && et < 37500.) {
1197  return prob; // region of non-interpolation for pdfs
1198  }
1199  double bin_width = 5000.;
1200  if (7000. < et && et < 10000.) {
1201  bin_width = 3000.;
1202  }
1203  if (et < 7000.) {
1204  bin_width = 2000.;
1205  }
1206  const double GeV = 1000;
1207  const double eTHistBins[s_fnEtBinsHist] = { 6. * GeV, 8.5 * GeV,
1208  12.5 * GeV, 17.5 * GeV,
1209  22.5 * GeV, 32.5 * GeV,
1210  42.5 * GeV };
1211  double bin_center = eTHistBins[etbin];
1212  if (etbin == 4 && et >= 27500.) {
1213  bin_center = 27500.; // special: interpolate starting from 27.5 here
1214  }
1215  if (etbin == 5 && et >= 37500.) {
1216  bin_center = 37500.; // special: interpolate starting from 37.5 here
1217  }
1218  if (et > bin_center) {
1219  double prob_next = prob;
1220  if (etbin + 1 <= 6) {
1221  // account for potential histogram bin inequalities
1222  int NbinsPlus =
1223  fPDFbins[s_or_b][ipbin][etbin + 1][etabin][var]->GetNbinsX();
1224  int binplus = bin;
1225  if (Nbins < NbinsPlus) {
1226  binplus = int(round(bin * (Nbins / NbinsPlus)));
1227  } else if (Nbins > NbinsPlus) {
1228  binplus = int(round(bin * (NbinsPlus / Nbins)));
1229  }
1230  // do interpolation
1231  double integral_next =
1232  double(fPDFbins[s_or_b][ipbin][etbin + 1][etabin][var]->Integral());
1233  prob_next =
1234  double(fPDFbins[s_or_b][ipbin][etbin + 1][etabin][var]->GetBinContent(
1235  binplus)) /
1236  integral_next;
1237  return prob + (prob_next - prob) * (et - bin_center) / (bin_width);
1238  }
1239  }
1240  // or else if et < bin_center :
1241  double prob_before = prob;
1242  if (etbin - 1 >= 0) {
1243  // account for potential histogram bin inequalities
1244  int NbinsMinus =
1245  fPDFbins[s_or_b][ipbin][etbin - 1][etabin][var]->GetNbinsX();
1246  int binminus = bin;
1247  if (Nbins < NbinsMinus) {
1248  binminus = int(round(bin * (Nbins / NbinsMinus)));
1249  } else if (Nbins > NbinsMinus) {
1250  binminus = int(round(bin * (NbinsMinus / Nbins)));
1251  }
1252  double integral_before =
1253  double(fPDFbins[s_or_b][ipbin][etbin - 1][etabin][var]->Integral());
1254  prob_before =
1255  double(fPDFbins[s_or_b][ipbin][etbin - 1][etabin][var]->GetBinContent(
1256  binminus)) /
1257  integral_before;
1258  }
1259  return prob - (prob - prob_before) * (bin_center - et) / (bin_width);
1260 }
1261 
1262 //----------------------------------------------------------------------------------------
1263 
1264 // These are the variables availalble in the likelihood.
1265 const std::string Root::TElectronLikelihoodTool::s_fVariables[s_fnVariables] = {
1266  "el_d0significance",
1267  "el_eratio",
1268  "el_deltaeta1",
1269  "el_f1",
1270  "el_f3",
1271  "el_reta",
1272  "el_rhad",
1273  "el_rphi",
1274  "el_trackd0pvunbiased",
1275  "el_weta2",
1276  "el_DeltaPoverP",
1277  "el_deltaphiRescaled",
1278  "el_TRT_PID"
1279 };
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::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:976
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: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:58
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
Root::TElectronLikelihoodTool::getLikelihoodEtHistBin
static unsigned int getLikelihoodEtHistBin(double eT)
Coarse Et binning. Used for the likelihood pdfs.
Definition: TElectronLikelihoodTool.cxx:1004
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
covarianceTool.prob
prob
Definition: covarianceTool.py:678
Root::TElectronLikelihoodTool::calculate
double calculate(LikeEnum::LHCalcVars_t &vars_struct) const
Definition: TElectronLikelihoodTool.cxx:673
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: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
Root::TElectronLikelihoodTool::getBinName
static std::string getBinName(int etbin, int etabin, int ipbin, const std::string &iptype)
Definition: TElectronLikelihoodTool.cxx:1063
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:148
Root::TElectronLikelihoodTool::InterpolateCuts
double InterpolateCuts(const std::vector< double > &cuts, const std::vector< double > &cuts_4gev, double et, double eta) const
Definition: TElectronLikelihoodTool.cxx:1100
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
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
python.LArMinBiasAlgConfig.int
int
Definition: LArMinBiasAlgConfig.py:59
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::s_fVariables
static const std::string s_fVariables[s_fnVariables]
Definition: TElectronLikelihoodTool.h:337
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:228
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:719
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:1081
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:817
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:1168
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:988
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:1024
read_hist_ntuple.f1
f1
Definition: read_hist_ntuple.py:4