ATLAS Offline Software
BTaggingEfficiencyTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
12 
13 // for the onnxtool
15 
18 
19 #include "TSpline.h"
20 
21 #include <algorithm>
22 
23 using CP::CorrectionCode;
24 using CP::SystematicSet;
27 
32 using Analysis::Total;
33 using Analysis::SFEigen;
35 using Analysis::SFNamed;
36 using Analysis::None;
39 
40 using xAOD::IParticle;
41 
42 // The following essentially duplicates code that already exists in package ParticleJetTools (in JetFlavourInfo.cxx).
43 // This duplication isn't desirable, but the alternative (to use ParticleJetTools directly) pulls in a lot of dependencies.
44 
45 namespace {
46  // helper methods
47  std::string default_flexible(int flavsize, const std::string& suffix = ":default"){
48  std::string setting;
49  for(int i = 0 ; i < flavsize ; i++){
50  setting += std::to_string(i);
51  setting += suffix;
52  if(i != flavsize - 1){
53  setting += ";";
54  }
55  }
56  return setting;
57  }
58 
60 
61  const std::string labelB = "GhostBHadronsFinal";
62  const std::string labelC = "GhostCHadronsFinal";
63  const std::string labelTau = "GhostTausFinal";
64 
65  std::vector<const IParticle*> ghostB;
66  if (jet.getAssociatedObjects<IParticle>(labelB, ghostB) && ghostB.size() > 0) return 5;
67  std::vector<const IParticle*> ghostC;
68  if (jet.getAssociatedObjects<IParticle>(labelC, ghostC) && ghostC.size() > 0) return 4;
69  std::vector<const IParticle*> ghostTau;
70  if (jet.getAssociatedObjects<IParticle>(labelTau, ghostTau) && ghostTau.size() > 0) return 15;
71  return 0;
72  }
73 
75  // default label means "invalid"
76  int label = -1;
77 
78  // First try the new naming scheme
79  if (jet.getAttribute("ConeTruthLabelID",label)) return label;
80  // If that fails, revert to the old scheme. In this case, further testing is not very useful
81  jet.getAttribute("TruthLabelID", label);
82  return label;
83  }
84 
85  int ExclusiveConeHadronFlavourLabel (const xAOD::Jet& jet, bool doExtended = false) {
86  // default label means "invalid"
87  int label = -1;
88 
89  // We don't check the return value, as we would not be able to handle it gracefully anyway
90  if (doExtended) {
91  jet.getAttribute("HadronConeExclExtendedTruthLabelID",label);
92  } else {
93  jet.getAttribute("HadronConeExclTruthLabelID",label);
94  }
95  return label;
96  }
97 
98  int LargeJetTruthLabel(const xAOD::Jet& jet, const std::string& jetauthor){
99  int label = -1;
100  if (jetauthor != "AntiKt10UFOCSSKSoftDropBeta100Zcut10Jets"){
101  jet.getAttribute("R10TruthLabel_R22v1", label);
102  // The following large-jet truth labels
103  //jet.getAttribute("R10TruthLabel_R21Precision_2022v1", label);
104  //jet.getAttribute("R10TruthLabel_R21Precision", label);
105  }
106  return label;
107  }
108 
109  int jetFlavourLabel (const xAOD::Jet& jet, bool doConeLabelling, bool doOldLabelling, bool doExtended, bool doXbbTagging, const std::string& jetauthor) {
110  if (doXbbTagging){
111  return LargeJetTruthLabel(jet, jetauthor);
112  } else if (doConeLabelling){
113  return (doOldLabelling) ? ConeFinalPartonFlavourLabel(jet) : ExclusiveConeHadronFlavourLabel(jet, doExtended);
114  } else {
116  }
117  }
118 
119 
120  // local utility function: trim leading and trailing whitespace in the property strings
121  std::string trim(const std::string& str,
122  const std::string& whitespace = " \t") {
123  const auto strBegin = str.find_first_not_of(whitespace);
124  if (strBegin == std::string::npos)
125  return ""; // no content
126 
127  const auto strEnd = str.find_last_not_of(whitespace);
128  const auto strRange = strEnd - strBegin + 1;
129 
130  return str.substr(strBegin, strRange);
131  }
132 
133  // local utility function: split string into a vector of substrings separated by a specified separator
134  std::vector<std::string> split(const std::string& str, char token = ';') {
135  std::vector<std::string> result;
136  if (str.size() > 0) {
137  std::string::size_type end;
138  std::string tmp(str);
139  do {
140  end = tmp.find(token);
141  std::string entry = trim(tmp.substr(0,end));
142  if (entry.size() > 0) result.push_back(entry);
143  if (end != std::string::npos) tmp = tmp.substr(end+1);
144  } while (end != std::string::npos);
145  }
146  return result;
147  }
148 }
149 
150 BTaggingEfficiencyTool::BTaggingEfficiencyTool( const std::string & name) : asg::AsgTool( name ), m_selectionTool("") {
151  declareProperty("TaggerName", m_taggerName="", "tagging algorithm name as specified in CDI file");
152  declareProperty("OperatingPoint", m_OP="", "operating point as specified in CDI file");
153  declareProperty("JetAuthor", m_jetAuthor="", "jet collection & JVF/JVT specification in CDI file");
154  declareProperty("MinPt", m_minPt=-1, "minimum jet pT cut");
155  declareProperty("ScaleFactorFileName", m_SFFile = "", "name of the official scale factor calibration CDI file (uses PathResolver)");
156  declareProperty("UseDevelopmentFile", m_useDevFile = false, "specify whether or not to use the (PathResolver) area for temporary scale factor calibration CDI files");
157  declareProperty("EfficiencyFileName", m_EffFile = "", "name of optional user-provided MC efficiency CDI file");
158  declareProperty("EfficiencyConfig", m_EffConfigFile = "", "name of config file specifying which efficiency map to use with a given samples DSID");
159  declareProperty("ScaleFactorBCalibration", m_SFNames["B"] = "default", "name of b-jet scale factor calibration object");
160  declareProperty("ScaleFactorCCalibration", m_SFNames["C"] = "default", "name of c-jet scale factor calibration object");
161  declareProperty("ScaleFactorTCalibration", m_SFNames["T"] = "default", "name of tau-jet scale factor calibration object");
162  declareProperty("ScaleFactorLightCalibration", m_SFNames["Light"] = "default","name of light-flavour jet scale factor calibration object");
163  declareProperty("EigenvectorReductionB", m_EVReduction["B"] = "Loose", "b-jet scale factor Eigenvector reduction strategy; choose between 'Loose', 'Medium', 'Tight'");
164  declareProperty("EigenvectorReductionC", m_EVReduction["C"] = "Loose", "c-jet scale factor Eigenvector reduction strategy; choose between 'Loose', 'Medium', 'Tight'");
165  declareProperty("EigenvectorReductionLight", m_EVReduction["Light"] = "Loose", "light-flavour jet scale factor Eigenvector reduction strategy; choose between 'Loose', 'Medium', 'Tight'");
166  declareProperty("EfficiencyBCalibrations", m_EffNames["B"] = "default", "(semicolon-separated) name(s) of b-jet efficiency object(s)");
167  declareProperty("EfficiencyCCalibrations", m_EffNames["C"] = "default", "(semicolon-separated) name(s) of c-jet efficiency object(s)");
168  declareProperty("EfficiencyTCalibrations", m_EffNames["T"] = "default", "(semicolon-separated) name(s) of tau-jet efficiency object(s)");
169  declareProperty("EfficiencyLightCalibrations", m_EffNames["Light"] = "default", "(semicolon-separated) name(s) of light-flavour-jet efficiency object(s)");
170  declareProperty("UncertaintyBSuffix", m_uncertaintySuffixes["B"] = "","optional suffix for b-jet uncertainty naming");
171  declareProperty("UncertaintyCSuffix", m_uncertaintySuffixes["C"] = "","optional suffix for c-jet uncertainty naming");
172  declareProperty("UncertaintyTSuffix", m_uncertaintySuffixes["T"] = "","optional suffix for tau-jet uncertainty naming");
173  declareProperty("UncertaintyLightSuffix", m_uncertaintySuffixes["Light"] = "","optional suffix for light-flavour-jet uncertainty naming");
174  declareProperty("ExcludeFromEigenVectorTreatment", m_excludeFromEV = "", "(semicolon-separated) names of uncertainties to be excluded from all eigenvector decompositions (if used)");
175  declareProperty("ExcludeFromEigenVectorBTreatment", m_excludeFlvFromEV["B"] = "", "(semicolon-separated) names of uncertainties to be excluded from b-jet eigenvector decomposition (if used)");
176  declareProperty("ExcludeFromEigenVectorCTreatment", m_excludeFlvFromEV["C"] = "", "(semicolon-separated) names of uncertainties to be excluded from c-jet eigenvector decomposition (if used)");
177  declareProperty("ExcludeFromEigenVectorLightTreatment",m_excludeFlvFromEV["Light"] = "", "(semicolon-separated) names of uncertainties to be excluded from light-flavour-jet eigenvector decomposition (if used)");
178  declareProperty("ExcludeRecommendedFromEigenVectorTreatment", m_useRecommendedEVExclusions = false, "specify whether or not to add recommended lists to the user specified eigenvector decomposition exclusion lists");
179  // declareProperty("ExcludeJESFromEVTreatment", m_excludeJESFromEV = true, "specify whether or not to exclude JES uncertainties from eigenvector decomposition (if used)");
180  declareProperty("SystematicsStrategy", m_systStrategy = "SFEigen", "name of systematics model; presently choose between 'SFEigen' and 'Envelope'");
181  declareProperty("ConeFlavourLabel", m_coneFlavourLabel = true, "specify whether or not to use the cone-based flavour labelling instead of the default ghost association based labelling");
182  declareProperty("ExtendedFlavourLabel", m_extFlavourLabel = false, "specify whether or not to use an 'extended' flavour labelling (allowing for multiple HF hadrons or perhaps partons)");
183  declareProperty("OldConeFlavourLabel", m_oldConeFlavourLabel = false, "when using cone-based flavour labelling, specify whether or not to use the (deprecated) Run-1 legacy labelling");
184  declareProperty("IgnoreOutOfValidityRange", m_ignoreOutOfValidityRange = false, "ignore out-of-extrapolation-range errors as returned by the underlying tool");
185  declareProperty( "useCTagging", m_useCTag=false, "Enabled only for FixedCut or Continuous WPs: define wether the cuts refer to b-tagging or c-tagging");
186  // if it is empty, the onnx tool won't be initialised
187  declareProperty( "pathToONNX", m_pathToONNX = "", "path to the onnx file that will be used for inference");
188  // experimental options
189  declareProperty("useFlexibleConfig", m_useFlex = false, "Setup the flexible configuration of the xAODBTaggingEfficiencyTool with alternate labeling");
190  declareProperty("doXbbTagging", m_doXbbTagging = false, "Configure the xAODBTaggingEfficiencyTool to perform alternate labeling on large radius jets (typically X->bb tagging)");
191  declareProperty("FlexibleScaleFactorCalibrations", m_SFName_flex = "", "(semicolon-separated) name of scale factor calibration object for (0,1,2..) indexed flavour labels, e.g. '0:default;1:default;2:default;3:default' ");
192  declareProperty("FlexibleEfficiencyCalibrations", m_EffNames_flex = "", "(semicolon-separated) name(s) of efficiency object(s) names for (0,1,2..) indexed flavour labels, e.g. '0:default;1:default;2:default;3:default' ");
193  declareProperty("FlexibleEigenvectorReduction", m_EVReduction_flex = "", "(semicolon-separated) list of eigenvector reduction strategy for (0,1,2..) indexed flavour labels; choose between 'Loose', 'Medium', 'Tight' for different labels, e.g. '0:Loose;1:Loose;2:Loose' ");
194  declareProperty("FlexibleUncertaintySuffix", m_uncertaintySuffixes_flex = "", "optional (semicolon-separated) list of suffixes for (0,1,2..) indexed flavour label uncertainty naming, e.g. '0:;1:;2:;3:' ");
195  declareProperty("FlexibleExcludeFromEVTreatment", m_excludeFlvFromEV_flex = "", "(semicolon-separated) names of uncertainties to be excluded from (0,1,2..) indexed flavour eigenvector decompositions (if used), e.g. '0:;1:;2:;3:' ");
196 
197  // initialise some variables needed for caching
198  // TODO : add configuration of the mapIndices - rather than just using the default of 0
199  //m_mapIndices["Light"] = m_mapIndices["T"] = m_mapIndices["C"] = m_mapIndices["B"] = 0;
200  m_initialised = false;
201  m_applySyst = false;
202  m_isContinuous = false;
203  m_isContinuous2D = false;
205  // declare the selection tool to be private (not absolutely sure this is needed?)
206  m_selectionTool.declarePropertyFor(this, "BTaggingSelectionTool", "selection tool to be used internally");
207 }
208 
210  //delete m_CDI;
211 }
212 
214 
215 
216  ATH_MSG_INFO( " Hello BTaggingEfficiencyTool user... initializing");
217  ATH_MSG_INFO( " TaggerName = " << m_taggerName);
218  ATH_MSG_INFO( " OP = " << m_OP);
219  ATH_MSG_INFO( " m_systStrategy is " << m_systStrategy);
220 
221  // Use the PathResolver to find the full pathname (behind the scenes this can also be used to download the file),
222  // if the file cannot be found directly.
223  // For consistency with the PathResolver code, use the Boost library to check on this first possibility.
226  if (location == "") {
227  std::string prepend = "";
228  if (m_useDevFile) {
229  ATH_MSG_WARNING(" Attempting to retrieve b-tagging scale factor calibration file from development area");
230  prepend = "dev/";
231  }
232  prepend += "xAODBTaggingEfficiency/";
233  m_SFFile = prepend + m_SFFile;
235  if (m_SFFileFull == "")
236  ATH_MSG_WARNING(" Unable to retrieve b-tagging scale factor calibration file!");
237  else
238  ATH_MSG_DEBUG(" Retrieving b-tagging scale factor calibration file as " << m_SFFile);
239  } else {
241  }
242 
243  // The situation for the efficiency file is a bit simpler since it need not reside under "xAODBTaggingEfficiency"
246 
247 
248  // Strategies for eigenvector reductions (only relevant if eigenvector variations are used, of course).
249  // For now, we will assume that the strategy for tau "jets" is identical to that for c jets.
250  std::map<std::string, Analysis::EVReductionStrategy> EVRedStrategies, mappings;
251  mappings["Loose"] = Analysis::Loose;
252  mappings["Medium"] = Analysis::Medium;
253  mappings["Tight"] = Analysis::Tight;
254 
255 
256  // Now that we know the CDI file location, let's check if the configuration provided is correct
258  if(!Reader.checkConfig(m_taggerName, m_jetAuthor, m_OP, msgLvl(MSG::DEBUG))){
259  ATH_MSG_ERROR( "BTaggingEfficiencyTool configuration is invalid - follow the above suggestions to correct your config!");
260  return StatusCode::FAILURE;
261  };
262  if (msgLvl(MSG::INFO)) {
263  ATH_MSG_INFO( " --- Calibration file configuration options ---" );
264  Reader.printTaggers();
265  Reader.printJetCollections();
266  Reader.printWorkingPoints();
267  }
268 
269  std::vector<std::string> config_labels = Reader.getLabels(); // the labels compatible with this configuration
270  std::vector<std::string> flavours;
271  // "pack" the efficiency map names for each flavour. Note that multiple, semicolon separated, entries may exist; so this needs to be decoded first
272  std::map<std::string, std::vector<std::string> > EffNames;
273  std::vector<std::string> EVflavours = { "B", "C", "Light" }; // ideally this would also come from the metadata of the CDI file as well...
274  // specify which systematic variations are to be excluded from the eigenvector decomposition
275  std::map<std::string, std::vector<std::string> > excludeFromEVCov;
276  std::vector<std::string> to_exclude = split(m_excludeFromEV); // uncertainties to exclude from all flavours
277 
278  if(!m_useFlex){
279 
280  if(m_doXbbTagging){
281  ATH_MSG_ERROR( "BTaggingEfficiencyTool configuration is invalid - cannot perform Xbb tagging without flexible configuration.");
282  return StatusCode::FAILURE;
283  }
284 
285  //if a configuration file was provided for efficiency maps, overwrite the efficiency map selection with the one provided in the first line of the config
286  if(not m_EffConfigFile.empty()){
288  std::ifstream eff_config_file(m_EffConfigFile);
289 
290  std::string str;
291  std::getline(eff_config_file, str);
292 
293  m_EffNames["B"] = str;
294  m_EffNames["C"] = str;
295  m_EffNames["T"] = str;
296  m_EffNames["Light"] = str;
297 
298  while (std::getline(eff_config_file, str)) {
299  std::vector<std::string> dsid_and_effmap = split(str,':');
300  unsigned int dsid = std::stoul( dsid_and_effmap[0] );
301  unsigned int map_index = std::stoul( dsid_and_effmap[1] );
302  m_DSID_to_MapIndex[dsid] = map_index;
303  }
304  }
305 
306 
307 
308  flavours = { "B", "C", "Light", "T"};
309 
310  for (auto const& flavour : flavours) {
311  EffNames[flavour] = split(m_EffNames[flavour]);
312  }
313 
314  ATH_MSG_INFO( " b-jet SF/eff calibration = " << m_SFNames["B"] << " / " << m_EffNames["B"]);
315  ATH_MSG_INFO( " c-jet SF/eff calibration = " << m_SFNames["C"] << " / " << m_EffNames["C"]);
316  ATH_MSG_INFO( " tau-jet SF/eff calibration = " << m_SFNames["T"] << " / " << m_EffNames["T"]);
317  ATH_MSG_INFO( " light-jet SF/eff calibration = " << m_SFNames["Light"] << " / " << m_EffNames["Light"]);
318  ATH_MSG_INFO( " JetAuthor = " << m_jetAuthor);
319 
320 
321  } else {
322 
323  // Set defaults for the following, based on flavour label
324  // metadata if any of the following properties are not set:
325  // - FlexibleScaleFactorCalibrations
326  // - FlexibleEfficiencyCalibrations
327  // - FlexibleEigenvectorReduction
328  // - FlexibleUncertaintySuffix
329  // - FlexibleExcludeFromEVTreatment
330 
331  flavours = config_labels; // set the flavours vector from CDI metadata
332  m_flex_labels = flavours; // set the label scheme, for use elsewhere
333  for(const std::string& label : m_flex_labels){
334  m_flex_label_integers.push_back(getFlavourID(label, false)); // populate the ordered flavour ID vector
335  }
336  int size_of_labels = flavours.size();
337  if (m_SFName_flex.empty()){
338  m_SFName_flex = default_flexible(flavours.size(), ":default");
339  } else {ATH_MSG_INFO(" Setting m_SFName_flex : " << m_SFName_flex);}
340  if (m_EffNames_flex.empty()){
341  m_EffNames_flex = default_flexible(flavours.size(), ":default");
342  } else {ATH_MSG_INFO(" Setting m_EffNames_flex : " << m_EffNames_flex);}
343  if (m_EVReduction_flex.empty()){
344  m_EVReduction_flex = default_flexible(flavours.size(), ":Loose");
345  } else {ATH_MSG_INFO(" Setting m_EVReduction_flex : " << m_EVReduction_flex);}
346  if (m_uncertaintySuffixes_flex.empty()){
347  m_uncertaintySuffixes_flex = default_flexible(flavours.size(), ":");
348  } else {ATH_MSG_INFO(" Setting m_uncertaintySuffixes_flex : " << m_uncertaintySuffixes_flex);}
349  if (m_excludeFlvFromEV_flex.empty()){
350  m_excludeFlvFromEV_flex = default_flexible(flavours.size(), ":");
351  } else {ATH_MSG_INFO(" Setting m_excludeFlvFromEV_flex : " << m_excludeFlvFromEV_flex);}
352 
353  // empty m_SFNames (filled by the 'default' setting), in the flexible method we want to use the labels found in the CDI file meta-data
354  m_SFNames.clear();
355  std::vector<std::string> efficiencies_map = split(m_EffNames_flex); // split to {"0:default", "1:47100,47200,default", "2:default", "3:default"}
356  for (auto const& effconfig : efficiencies_map) {
357  std::vector<std::string> effmap = split(effconfig, ':'); // split to {"0", "default"}
358  if(effmap.size() != 2){ // check if first flavour label config is written properly // || std::stoi(effmap.at(0)) > (int)flavours.size()
359  ATH_MSG_ERROR( "BTaggingEfficiencyTool configuration is invalid - efficiency files not included properly in the (experimental) flexible configuration!");
360  return StatusCode::FAILURE;
361  }
362  int index = std::stoi(effmap.at(0)); // index of flavour label in 'flavours' vector
363  std::vector<std::string> effcalibs; // vector of efficiency calibrations
364  if(effmap.at(1) != "default"){
365  effcalibs = split(effmap.at(1), ',');
366  } else {
367  effcalibs.push_back(effmap.at(1));
368  }
369  std::string flavour_name = flavours.at(index);
370  m_EffNames[flavour_name] = effmap.at(1); // set this for posterity
371  EffNames[flavour_name] = effcalibs;
372  }
373 
374  std::vector<std::string> scalefactor_map = split(m_SFName_flex); // split to {"0:default", "1:47100,47200,default", "2:default", "3:default"}
375  for (auto const& sfconfig : scalefactor_map) {
376  std::vector<std::string> sfmap = split(sfconfig, ':'); // split to {"0", "default"}
377  if(sfmap.size() != 2){ // check if first flavour label config is written properly // || std::stoi(sfmap.at(0)) > (int)flavours.size()
378  ATH_MSG_ERROR( "BTaggingEfficiencyTool configuration is invalid - efficiency files not included properly in the (experimental) flexible configuration!");
379  return StatusCode::FAILURE;
380  }
381  int index = std::stoi(sfmap.at(0)); // index of flavour label in 'flavours' vector
382  std::string flavour_name = flavours.at(index);
383  m_SFNames[flavour_name] = sfmap.at(1);
384  }
385  for(const std::string& flav : flavours){
386  ATH_MSG_INFO( flav + " label SF/eff calibration = " + m_SFNames[flav] + " / " + m_EffNames[flav] ) ;
387  }
388 
389  // Now deal with the flexible configurations
390  EVflavours.clear(); // ideally this vector would also come from CDI file metadata
391  EVflavours = flavours; // for now, just set the vector of EV flavours to the flavours vector
392  // construct the flavour m_EVReduction map from m_EVReduction_flex index based configuration
393  std::vector<std::string> evreduction_map = split(m_EVReduction_flex);
394  for (auto const& evred : evreduction_map) {
395  std::vector<std::string> evredmap = split(evred, ':'); // split to {"0", "Loose"}
396  if(evredmap.size() != 2){
397  if(std::stoi(evredmap.at(0)) < size_of_labels){
398  evredmap.push_back("");
399  } else {
400  ATH_MSG_ERROR( "BTaggingEfficiencyTool configuration is invalid - reduction strategies not set properly in the (experimental) flexible configuration!");
401  return StatusCode::FAILURE;
402  }
403  }
404  int index = std::stoi(evredmap.at(0)); // index of flavour label in 'flavours' vector
405  const std::string& flavour_name = flavours.at(index);
406  m_EVReduction[flavour_name] = evredmap.at(1);
407  }
408 
409  // construct the flavour m_excludeFlvFromEV map from m_excludeFlvFromEV_flex index based configuration
410  std::vector<std::string> exclusion_map = split(m_excludeFlvFromEV_flex);
411  for (auto const& excl : exclusion_map) {
412  std::vector<std::string> exclmap = split(excl, ':'); // split to {"0", "uncertainty1,uncertainty2,..,uncertaintyN"}
413  if(exclmap.size() != 2){
414  if(std::stoi(exclmap.at(0)) < size_of_labels){
415  exclmap.push_back("");
416  } else {
417  ATH_MSG_ERROR( "BTaggingEfficiencyTool configuration is invalid - uncertainty exclusion not set properly in the (experimental) flexible configuration!");
418  return StatusCode::FAILURE;
419  }
420  }
421  int index = std::stoi(exclmap.at(0)); // index of flavour label in 'flavours' vector
422  std::vector<std::string> uncertainties_to_exclude = split(exclmap.at(1), ',');; // vector of uncertainties to exclude for this flavour
423  const std::string& flavour_name = flavours.at(index);
424  m_excludeFlvFromEV[flavour_name] = exclmap.at(1);
425  }
426  }
427 
428  // set the reduction per EV flavour/label, and exclude uncertainties from EV reduction
429  for (auto const& flavour : EVflavours) {
430  EVRedStrategies[flavour] = mappings.find(trim(m_EVReduction[flavour])) == mappings.end() ? mappings["Loose"] : mappings[trim(m_EVReduction[flavour])];
431  excludeFromEVCov[flavour] = to_exclude; // look for uncertainties to be excluded for all flavours
432  std::vector<std::string> further_exclude = split(m_excludeFlvFromEV[flavour]); // now grab the flavour/label specific uncertainties to exclude
433  excludeFromEVCov[flavour].insert(excludeFromEVCov[flavour].end(), further_exclude.begin(), further_exclude.end()); // Append to the existing list
434  }
435 
436  // now, handle the edge-cases of EV reduction and extra uncertainties
437  // e.g. C - T calibration duplication in "conventional" flavour labeling
438  // check if the labels are "conventional"
439  std::vector<std::string> conventional_labels = {"B", "C", "Light", "T"};
440  if (flavours == conventional_labels) {
442  }
444  // if using conventional label, we can use the same logic as always
445  EVRedStrategies["T"] = EVRedStrategies["C"];
446 
447  // For the SFEigen strategy, tau "jets" are treated differently from other flavours.
448  // First, copy the charm-jet calibration settings
449  excludeFromEVCov["T"] = excludeFromEVCov["C"];
450 
451  // Then ensure that the charm -> tau extrapolation uncertainty is added.
452  // Technically the additional condition should never be necessary, as existing entries should not apply to tau "jets"; so this is mostly to protect users against a duplicate specification
453  if (m_systStrategy != "Envelope" && std::find(excludeFromEVCov["T"].begin(), excludeFromEVCov["T"].end(), "extrapolation from charm") == excludeFromEVCov["T"].end())
454  excludeFromEVCov["T"].push_back("extrapolation from charm");
455 
456  //high pt extrapolation uncertainties
457  if(m_OP.find("Continuous") != std::string::npos){
458  excludeFromEVCov["B"].push_back("extrapolation_pt_b_Eigen*");
459  excludeFromEVCov["C"].push_back("extrapolation_pt_c_Eigen*");
460  excludeFromEVCov["Light"].push_back("extrapolation_pt_l_Eigen*");
461  excludeFromEVCov["T"].push_back("extrapolation_pt_c_Eigen*");
462  }
463  }
464 
465  if (m_OP == "Continuous") {
466  // continuous tagging is special in two respects:
467  // 1 the tag weight needs to be retrieved
468  // 2 the generator dependent scale factor rescaling is done differently, and therefore
469  // CalibrationDataInterfaceROOT::getWeightScaleFactor() instead of
470  // CalibrationDataInterfaceROOT::getScaleFactor() must be used
471  m_isContinuous = true;
472  }
473  else if (m_OP.find("Continuous2D") != std::string::npos) {
474  m_isContinuous2D = true;
475  }
476  // Note that the instantiation below does not leave a choice: the Eigenvector variations and generator-specific scale factors are always used
477  std::vector<std::string> jetAliases;
478  m_CDI = std::shared_ptr<Analysis::CalibrationDataInterfaceROOT>( new Analysis::CalibrationDataInterfaceROOT(
479  m_taggerName, // tagger name: always needed
480  m_SFFileFull.c_str(), // full pathname of the SF calibration file: always needed
481  (m_EffFile == "") ? 0 : m_EffFile.c_str(), // full pathname of optional efficiency file
482  jetAliases, // since we configure the jet "collection name" by hand, we don't need this
483  m_SFNames, // names of the scale factor calibrations to be used
484  EffNames, // names of the efficiency calibrations to be used (can be multiple per flavour)
485  excludeFromEVCov, // names of systematic uncertainties to be excluded from the EV decomposition
486  EVRedStrategies, // strategies for eigenvector reductions
487  m_systStrategy != "Envelope", // assume that eigenvector variations will be used unless the "Envelope" model is used
489  true, // use MC/MC scale factors
490  false, // do not use topology rescaling (only relevant for pseudo-continuous tagging)
491  m_useRecommendedEVExclusions, // if true, add pre-set lists of uncertainties to be excluded from EV decomposition
492  msgLvl(MSG::DEBUG), // if false, suppress any non-error/warning messages
493  flavours // vector of flavour labels, conventional or not
494  ));
495 
497  ATH_MSG_INFO("BTEffTool->initialize : setMapIndex(Light)");
498  setMapIndex("Light",0);
499  ATH_MSG_INFO("BTEffTool->initialize : setMapIndex(C)");
500  setMapIndex("C",0);
501  ATH_MSG_INFO("BTEffTool->initialize : setMapIndex(B)");
502  setMapIndex("B",0);
503  ATH_MSG_INFO("BTEffTool->initialize : setMapIndex(T)");
504  setMapIndex("T",0);
505  } else {
506  for(const auto& flavour : flavours){
507  // set map index for each flavour (label) index
508  ATH_MSG_INFO(" - - -BTEffTool->initialize : setMapIndex(" << flavour << ")");
509  setMapIndex(flavour, 0);
510  }
511  }
512 
513  ATH_MSG_INFO( "Using systematics model " << m_systStrategy);
514  if (m_systStrategy != "Envelope" && m_useRecommendedEVExclusions) ATH_MSG_INFO( "excluding pre-set uncertainties from eigenvector decomposition");
515 
516  // We have a double loop over flavours here.. not nice but this is to ensure that the suffixes are always well determined before using them.
517  // Note that (in the SFEigen model) suffixes are attached to eigenvector variations only (the idea being that named uncertainties, if used, are likely to be correlated).
518  std::vector<std::string> suffixes;
520  for (int i = 0; i < 4; ++i) { // four flavours in conventional label scheme
521  std::string flav = flavours[i]; if (flav == "T") flav = "C";
522  // add an underscore to any specified suffix (if specified and if not already starting with a suffix)
523  std::string test = trim(m_uncertaintySuffixes[flav]);
524  if (test.length() > 0 && test[0] != '_') test.insert(0,"_");
525  suffixes.push_back(test);
526  }
527  } else {
528  // Need to handle the suffixes for the generic labels
529  std::vector<std::string> suffixvec = split(m_uncertaintySuffixes_flex);
530  int size_of_labels = flavours.size();
531  for (auto const& suff : suffixvec) {
532  std::vector<std::string> suffmap = split(suff, ':'); // split to {"0", "uncertainty1,uncertainty2,..,uncertaintyN"}
533  if(suffmap.size() != 2){
534  if(std::stoi(suffmap.at(0)) < size_of_labels){
535  suffmap.push_back("");
536  } else {
537  ATH_MSG_ERROR( "BTaggingEfficiencyTool configuration is invalid - suffix configuration not set properly in the (experimental) flexible configuration!");
538  return StatusCode::FAILURE;
539  }
540  }
541  int index = std::stoi(suffmap.at(0)); // index of flavour label in 'flavours' vector
542  std::string flavour_name = flavours.at(index);
543  // add an underscore to any specified suffix (if specified and if not already starting with a suffix)
544  std::string suffix = trim(suffmap.at(1));
545  if (suffix.length() > 0 && suffix[0] != '_') suffix.insert(0,"_");
546  suffixes.push_back(suffix);
547  }
548  }
549 
550  // If the tool has not already been initialised and m_OP and m_jetAuthor have been set - ie via the properties "OperatingPoint" and "JetAuthor"
551  // then autmatically set things up to use these by default
552  // All this must happen before registerSystematics otherwise that won't work
553  for (long unsigned int i = 0; i < flavours.size(); ++i) {
554  // For each flavour, we check the validity of the initialization of the CalibrationInterfaceROOT object (m_CDI)
555  unsigned int flavourID;
557  flavourID = getFlavourID(flavours[i]);
558  } else {
559  flavourID = getFlavourID(flavours[i], false); // in flexible scheme, need to specify the new labels in getFlavourID
560  }
561  // std::map<unsigned int, unsigned int>::const_iterator
562  auto mapIter = m_SFIndices.find(flavourID);
563  if( mapIter==m_SFIndices.end()) { // if the flavour doesn't have an entry need to fail the initialization
564  ATH_MSG_ERROR( "No entry for flavour " << flavourID << " which is " << flavours[i] << " in SFIndices map, invalid initialization");
565  return StatusCode::FAILURE;
566  }
567  int id = mapIter->second;
568  // Implement the different strategies for dealing with uncertainties here.
569  if (m_systStrategy == "SFEigen" || m_systStrategy == "SFGlobalEigen") {
570  //
571  // Generally recommended model: use eigenvector variations. Notes:
572  // - The list of systematics to be excluded from the eigenvector variation approach is dynamic.
573  // - The tau SF are identical to the c-jet ones, with merely one additional uncertainty assigned due to the extrapolation.
574  //
575  unsigned int flavourIDRef;
577  flavourIDRef = (flavourID == 15) ? 4 : flavourID;
578  } else {
579  flavourIDRef = flavourID;
580  }
581  int idRef = m_SFIndices.find(flavourIDRef)->second;
582  // First, handle any named variations
583  std::vector<std::string> systematics = m_CDI->listScaleFactorUncertainties(idRef, flavours.at(i), true); // flavours[i] should be "B", "C", "Light", or "T"
584  // Replace any spaces with underscores (this is to make ROOT browsing happy).
585  // Also, remove the "extrapolation" uncertainty from the list (it will be added later under Extrapolation rather than SFNamed).
586 
587  auto it = std::remove (systematics.begin(), systematics.end(),
588  "extrapolation");
589  bool hasExtrapolation = (it != systematics.end());
590  systematics.erase (it, systematics.end());
591  // C++20 alternative:
592  //bool hasExtrapolation = std::erase (systematics, "extrapolation") > 0;
593 
594  for (auto& systematic : systematics) {
595  std::replace_if(systematic.begin(), systematic.end(), [] (char c) { return c == ' '; }, '_'); // <--- This just replaces spaces with underscores
596  // We don't add suffixes here but only for EV variations (see JIRA: AFT-343)
597  }
598 
599  if (!addSystematics(systematics, flavourID, SFNamed)) { // Add the SFNamed to m_systematicsInfo
600  ATH_MSG_ERROR("SFEigen model: error adding named systematics for flavour " << getLabel(flavourIDRef) << ", invalid initialization"); // For each uncertainty type, have to add ALL uncertainties pertaining to that type
601  return StatusCode::FAILURE;
602  }
603 
604  // Add here the extrapolation uncertainty (if it exists -- which ought to be the case).
605  // "Cosmetic" fix: the outside world wants to see "FT_EFF_" prefixes. On the other hand, like for the above named uncertainties, we don't add suffixes here
606  if (hasExtrapolation) {
607  std::vector<std::string> extrapSyst; extrapSyst.push_back(std::string("FT_EFF_extrapolation")); // Add the EXTRAPOLATION to m_systematicsInfo
608  if (! addSystematics(extrapSyst, flavourID, Extrapolation)) {
609  ATH_MSG_ERROR("SFEigen model: error adding extrapolation uncertainty for flavour " << getLabel(flavourIDRef) << ", invalid initialization");
610  return StatusCode::FAILURE;
611  }
612  }
613 
614  // And then the eigenvector variations
615  std::vector<std::string> eigenSysts;
616  if (m_systStrategy == "SFEigen"){
618  eigenSysts = makeEigenSyst(getLabel(flavourIDRef),m_CDI->getNumVariations(idRef, SFEigen, getLabel(flavourID)), suffixes[i]); // Add the eigenvariations to m_systematicsInfo
619  } else {
620  eigenSysts = makeEigenSyst(getLabel(flavourIDRef),m_CDI->getNumVariations(idRef, SFEigen, flavours[i]), suffixes[i]); // Add the eigenvariations to m_systematicsInfo
621  }
622  if (!addSystematics(eigenSysts, flavourID, SFEigen)) {
623  ATH_MSG_ERROR("SFEigen model: error adding eigenvector systematics for flavour " << getLabel(flavourIDRef) << ", invalid initialization");
624  return StatusCode::FAILURE;
625  }
626  } else if (m_systStrategy == "SFGlobalEigen") {
628 
629  // we have to add the SFGlobalEigen systematics like this...
631  eigenSysts = makeEigenSyst(getLabel(flavourIDRef),m_CDI->getNumVariations(idRef, SFGlobalEigen, getLabel(flavourID)), suffixes[i]); // Add the eigenvariations to m_systematicsInfo
632  } else {
633  std::vector<std::string> eigenSysts = makeEigenSyst(getLabel(flavourIDRef),m_CDI->getNumVariations(idRef, SFGlobalEigen, flavours[i]), suffixes[i]); // Add the eigenvariations to m_systematicsInfo
634  }
635  if (!addSystematics(eigenSysts, flavourID, SFGlobalEigen)) {
636  ATH_MSG_ERROR("SFGlobalEigen model: error adding eigenvector systematics for flavour " << getLabel(flavourIDRef) << " ie " << getLabel(flavourID) << ", invalid initialization");
637  return StatusCode::FAILURE;
638  }
639 
641  }
642  // The above should cover all uncertainties except the charm -> tau extrapolation; so we take care of that here.
643  if (flavourID == 15) {
644  // First extract the complete list of uncertainties for taus
645  std::vector<std::string> all_systematics = m_CDI->listScaleFactorUncertainties(id, getLabel(flavourID));
646  // And from this list extract only this particular uncertainty (if it exists)
647  const std::string s_tau_extrap = "extrapolation from charm";
648  if (std::find(all_systematics.begin(), all_systematics.end(), s_tau_extrap) != all_systematics.end()) {
649  // Again, we don't add the suffix here (per JIRA: AFT-343)
650  std::string entry = "FT_EFF_extrapolation_from_charm"; // entry.append(suffixes[i]);
651  std::vector<std::string> extrapSyst; extrapSyst.push_back(entry);
652  if (! addSystematics(extrapSyst, flavourID, TauExtrapolation)) { // <--- Add the TauExtrapolation to m_systematicsInfo
653  ATH_MSG_ERROR("SFEigen model: error adding charm->tau systematics for flavour " << getLabel(flavourID) << ", invalid initialization");
654  return StatusCode::FAILURE;
655  }
656  }
657  }
658  } else if (m_systStrategy == "Envelope") {
659  //
660  // Simplified model: use uncertainty envelopes supplemented by a (common) extrapolation uncertainty
661  // (since the extrapolation uncertainties aren't included in the Total uncertainty). Notes:
662  // - The tau SF are identical to the c-jet ones, with merely one additional uncertainty assigned due to the extrapolation.
663  // - The "total" uncertainty is always expected to be available; the code will bomb if this is not the case.
664  // Also, the "total" uncertainties for different flavours are assumed to be uncorrelated.
665  //
666  unsigned int flavourIDRef = (flavourID == 15) ? 4 : flavourID;
667  int idRef = m_SFIndices.find(flavourIDRef)->second;
668  // First, handle the Total variations; these need different prefixes to reflect them being uncorrelated
669  std::vector<std::string> all_ref_systematics = m_CDI->listScaleFactorUncertainties(idRef,getLabel(flavourID),false);
670  const std::string s_total = "systematics";
671  if (std::find(all_ref_systematics.begin(), all_ref_systematics.end(), s_total) == all_ref_systematics.end()) {
672  ATH_MSG_ERROR("Envelope model: required uncertainty " << s_total << " not found for flavour " << getLabel(flavourIDRef)
673  << ", invalid initialization");
674  return StatusCode::FAILURE;
675  }
676  std::vector<std::string> totalSyst; totalSyst.push_back("FT_EFF_" + getLabel(flavourIDRef) + "_" + s_total + suffixes[i]);
677  if (! addSystematics(totalSyst, flavourID, Total)) {
678  ATH_MSG_ERROR("Envelope model: error adding systematics uncertainty for flavour " << getLabel(flavourIDRef)
679  << ", invalid initialization");
680  return StatusCode::FAILURE;
681  }
682  // Second, handle the extrapolation variations; these are shared between flavours (unless different suffixes are specified)
683  const std::string s_extrap = "extrapolation";
684  if (std::find(all_ref_systematics.begin(), all_ref_systematics.end(), s_extrap) != all_ref_systematics.end()) {
685  std::vector<std::string> extrapSyst; extrapSyst.push_back("FT_EFF_" + s_extrap + suffixes[i]);
686  if (! addSystematics(extrapSyst, flavourID, Extrapolation)) {
687  ATH_MSG_ERROR("Envelope model: error adding extrapolation uncertainty for flavour " << getLabel(flavourIDRef)
688  << ", invalid initialization");
689  return StatusCode::FAILURE;
690  }
691  }
692  // Finally, handle the charm -> tau extrapolation (as in the above)
693  if (flavourID == 15) {
694  // First extract the complete list of uncertainties for taus
695  std::vector<std::string> all_systematics = m_CDI->listScaleFactorUncertainties(id, getLabel(flavourID));
696  // And from this list extract only this particular uncertainty (if it exists)
697  const std::string s_tau_extrap = "extrapolation from charm";
698  if (std::find(all_systematics.begin(), all_systematics.end(), s_tau_extrap) != all_systematics.end()) {
699  std::vector<std::string> extrapSyst; extrapSyst.push_back("FT_EFF_extrapolation_from_charm" + suffixes[i]);
700  if (! addSystematics(extrapSyst, flavourID, TauExtrapolation)) {
701  ATH_MSG_ERROR("Envelope model: error adding charm->tau systematics for flavour " << getLabel(flavourID) << ", invalid initialization");
702  return StatusCode::FAILURE;
703  }
704  }
705  }
706  }
707  } // end flavour loop
708 
709  // now fill the SystematicSet
710  for( std::map<SystematicVariation,SystInfo>::const_iterator mapIter = m_systematicsInfo.begin(); mapIter != m_systematicsInfo.end();++mapIter) {
711  const SystematicVariation & variation = mapIter->first;
712  m_systematics.insert(variation);
713  }
714  // systematics framework
715  SystematicRegistry & registry = SystematicRegistry::getInstance();
716  if( registry.registerSystematics(*this) != StatusCode::SUCCESS)
717  return StatusCode::FAILURE;
718 
719  // Finally, also initialise the selection tool, if needed (for now this is the case only for DL1 tag weight computations,
720  // so we do this only when DL1 is specified)
721  if (m_taggerName.find("DL1") != std::string::npos || m_taggerName.find("GN1") != std::string::npos || m_taggerName.find("GN2") != std::string::npos) {
722  m_selectionTool.setTypeAndName("BTaggingSelectionTool/" + name() + "_selection");
723  ATH_CHECK( m_selectionTool.setProperty("FlvTagCutDefinitionsFileName", m_SFFile) );
725  ATH_CHECK( m_selectionTool.setProperty("OperatingPoint", m_OP) );
728  ATH_CHECK( m_selectionTool.setProperty("useCTagging", m_useCTag) );
730  }
731 
732  // if the user decides to ignore these errors, at least make her/him aware of this
734  ATH_MSG_INFO("!!!!! You have chosen to disable out-of-validity return codes -- contact the Flavour Tagging group if such jets comprise a substantial part of the phase space in your analysis !!!!!");
735  }
736 
737  // create and initialise the onnx tool
738  if (m_pathToONNX != ""){
739  std::string pathtoonnxfile = PathResolverFindCalibFile(m_pathToONNX);
740  if (pathtoonnxfile == ""){
741  ATH_MSG_ERROR("ONNX error: Model file doesn't exist! Please set the property 'pathToONNX' to a valid ONNX file");
742  return StatusCode::FAILURE;
743  }
744  m_onnxUtil = std::make_unique<OnnxUtil> (m_pathToONNX);
745  m_onnxUtil->initialize();
746  }
747 
748  m_initialised = true;
749  return StatusCode::SUCCESS;
750 }
751 
754 {
755  if (! m_initialised) {
756  ATH_MSG_ERROR("BTaggingEfficiencyTool has not been initialised");
757  return CorrectionCode::Error;
758  }
759 
760  // get the btag label
761  int flavour{0};
762  if (m_using_conventional_labels){ // if not using conventional labels, so flavour label will have to be set by some other means...
764  }
765 
767  //const double pt = jet.pt();
768  //const double eta = jet.eta();
769  //const double tagwe = 0.7; // temporary testing
770  if (! fillVariables(jet, vars)) {
771  //if (! fillVariables(pt, eta, tagwe, vars)){
772  ATH_MSG_ERROR("unable to fill variables required for scale factor evaluation");
773  return CorrectionCode::Error;
774  }
775 
776  return getScaleFactor(flavour, vars, sf);
777 }
778 
781  float & sf)
782 {
783  if (! m_initialised) {
784  ATH_MSG_ERROR("BTaggingEfficiencyTool has not been initialised");
785  return CorrectionCode::Error;
786  }
787 
789 
790  unsigned int sfindex = 0;
791  unsigned int efindex = 0;
792 
793  if( !getIndices(flavour,sfindex,efindex)) { //<-------- This method returns true if it can find the sfindex and efindex corresponding to the flavour
794  // These indices are used internally in the CalibrationDataInterfaceROOT. They represent the index where
795  // the CalibrationDataContainer storing the calibration scalefactors/efficiencies are at in the CDIROOT (in m_objects in both cases, but needs a call to getMCScaleFactor in latter case)
796  // Once the container is retrieved by index, the CalibrationDataEigenVariations object is retrieved by container,
797  // which actually returns Up/Down variations, else return SF+SFError
798  ATH_MSG_ERROR("BTaggingEfficiencyTool::getScaleFactor call to getIndices failed " << flavour << " " << sfindex << " " << efindex);
799  return CorrectionCode::Error;
800  }
802  Uncertainty unc = None;
803  unsigned int unc_ind=0; // <----- This is the index of the variation internal to the CDIROOT object
804 
805  if( m_applySyst) { // indicate that we want to apply a systematic variation, i.e. return an up/down variation pair
806  unc = m_applyThisSyst.uncType; // type of systematic strategy...
807  if(!m_applyThisSyst.getIndex(flavour,unc_ind)) {
808  ATH_MSG_VERBOSE("getScaleFactor: requested variation cannot be applied to flavour " << getLabel(flavour) << ", returning nominal result");
809  unc = None;
810  }
811  }
812 
813  // In all likelihood, the "sfindex" and "efindex" need more work in the CDIROOT (or in the CDGEV)
814  status = (m_isContinuous || m_isContinuous2D) ? m_CDI->getWeightScaleFactor(v,sfindex,efindex, unc,unc_ind,result) : m_CDI->getScaleFactor(v,sfindex,efindex, unc,unc_ind,result, getLabel(flavour));
815 
816  // Interpret what has been retrieved;
817  // this depends both on the uncertainty type and on the up/down setting.
818  sf = result.first;
819  if (m_applySyst && unc != None) {
820  if (! (unc == SFEigen || unc == SFNamed || unc == SFGlobalEigen)){
821  sf += m_applyThisSyst.isUp ? result.second : -result.second ;
822  } else if (!m_applyThisSyst.isUp) {
823  sf = result.second; // otherwise, set the sf to the down variation (if down is requested)
824  } // otherwise, doing nothing will return the result.first value, which SHOULD represent the up variation
825  }
826 
827  switch (status) {
828  case Analysis::kError:
829  ATH_MSG_ERROR("BTaggingEfficiencyTool::getScaleFactor call to underlying code returned a kError!");
830  return CorrectionCode::Error;
831  case Analysis::kRange:
833  return m_ignoreOutOfValidityRange ? CorrectionCode::Ok : CorrectionCode::OutOfValidityRange;
834  case Analysis::kSuccess:
835  default:
836  return CorrectionCode::Ok;
837  }
838 }
839 
842 {
843  if (! m_initialised) return CorrectionCode::Error;
844 
845  // get the btag label
847 
849 
850  if (! fillVariables(jet, vars)) {
851  ATH_MSG_ERROR("unable to fill variables required for efficiency evaluation");
852  return CorrectionCode::Error;
853  }
854 
855  return getEfficiency(flavour, vars, eff);
856 }
857 
860  float & eff)
861 {
862  if (! m_initialised) return CorrectionCode::Error;
863 
865 
866  unsigned int sfindex = 0;
867  unsigned int efindex = 0;
868 
869  if( !getIndices(flavour,sfindex,efindex)) {
870  ATH_MSG_ERROR("BTaggingEfficiencyTool::getEfficiency call to getIndices failed " << flavour << " " << sfindex << " " << efindex);
871  return CorrectionCode::Error;
872  }
873  Uncertainty unc = None;
874  unsigned int unc_ind = 0;
875 
876  if( m_applySyst) {
877 
878  unc = m_applyThisSyst.uncType;
879  // if( m_applyThisSyst.isNamed) {
880  // unc = SFNamed;
881  // } else {
882  // unc = SFEigen;
883  // }
884 
885  if(!m_applyThisSyst.getIndex(flavour,unc_ind)) {
886  ATH_MSG_VERBOSE("getEfficiency: requested variation cannot be applied to flavour " << getLabel(flavour) << ", returning nominal result");
887  unc = None;
888  }
889  }
890 
891  CalibrationStatus status = m_CDI->getEfficiency(v,sfindex,efindex, unc,unc_ind,result, getLabel(flavour));
892  // Interpret what has been retrieved;
893  // this depends both on the uncertainty type and on the up/down setting.
894  eff = result.first; // central value or up variation
895  if (m_applySyst && unc != None) {
896  if (! (unc == SFEigen || unc == SFNamed)){
897  eff += m_applyThisSyst.isUp ? result.second : -result.second ;
898  } else if (!m_applyThisSyst.isUp) {
899  eff = result.second; // down variation
900  }
901  }
902 
903  switch (status) {
904  case Analysis::kError:
905  ATH_MSG_ERROR("BTaggingEfficiencyTool::getEfficiency call to underlying code returned a kError!");
906  return CorrectionCode::Error;
907  case Analysis::kRange:
909  return m_ignoreOutOfValidityRange ? CorrectionCode::Ok : CorrectionCode::OutOfValidityRange;
910  case Analysis::kSuccess:
911  default:
912  return CorrectionCode::Ok;
913  }
914 }
915 
918 {
919  if (! m_initialised) return CorrectionCode::Error;
920 
921  // get the btag label
923 
925  if (! fillVariables(jet, vars)) {
926  ATH_MSG_ERROR("unable to fill variables required for scale factor evaluation");
927  return CorrectionCode::Error;
928  }
929 
930  return getInefficiency (flavour, vars, eff);
931 }
932 
935  float & eff)
936 {
937  if (! m_initialised) return CorrectionCode::Error;
938 
940 
941  unsigned int sfindex = 0;
942  unsigned int efindex = 0;
943 
944  if( !getIndices(flavour,sfindex,efindex)) {
945  ATH_MSG_ERROR("BTaggingEfficiencyTool::getInefficiency call to getIndices failed " << flavour << " " << sfindex << " " << efindex);
946  return CorrectionCode::Error;
947  }
948  Uncertainty unc = None;
949  unsigned int unc_ind = 0;
950  if( m_applySyst) {
951 
952  unc = m_applyThisSyst.uncType;
953  // if( m_applyThisSyst.isNamed) {
954  // unc = SFNamed;
955  // } else {
956  // unc = SFEigen;
957  // }
958 
959  if(!m_applyThisSyst.getIndex(flavour,unc_ind)) {
960  ATH_MSG_VERBOSE("getInefficiency: requested variation cannot be applied to flavour " << getLabel(flavour)
961  << ", returning nominal result");
962  unc = None;
963  }
964  }
965 
966  CalibrationStatus status = m_CDI->getInefficiency(v, sfindex, efindex, unc, unc_ind, result, getLabel(flavour));
967  // Interpret what has been retrieved;
968  // this depends both on the uncertainty type and on the up/down setting.
969  // For the Total uncertainty, note also the sign change compared to e.g. getEfficiency().
970  eff = result.first; // central value or up variation
971  if (m_applySyst && unc != None) {
972  if (! (unc == SFEigen || unc == SFNamed))
973  eff += m_applyThisSyst.isUp ? -result.second : result.second ;
974  else if (!m_applyThisSyst.isUp) {
975  eff = result.second; // down variation
976  }
977  }
978 
979  switch (status) {
980  case Analysis::kError:
981  ATH_MSG_ERROR("BTaggingEfficiencyTool::getInefficiency call to underlying code returned a kError!");
982  return CorrectionCode::Error;
983  case Analysis::kRange:
985  return m_ignoreOutOfValidityRange ? CorrectionCode::Ok : CorrectionCode::OutOfValidityRange;
986  case Analysis::kSuccess:
987  default:
988  return CorrectionCode::Ok;
989  }
990 }
991 
994 {
995  if (! m_initialised) return CorrectionCode::Error;
996 
997  // get the btag label
999 
1001  if (! fillVariables(jet, vars)) {
1002  ATH_MSG_ERROR("unable to fill variables required for scale factor evaluation");
1003  return CorrectionCode::Error;
1004  }
1005 
1006  return getInefficiencyScaleFactor( flavour, vars, sf);
1007 }
1008 
1011  float & sf)
1012 {
1013  if (! m_initialised) return CorrectionCode::Error;
1014 
1016 
1017  unsigned int sfindex = 0;
1018  unsigned int efindex = 0;
1019 
1020  if( !getIndices(flavour,sfindex,efindex)) {
1021  ATH_MSG_ERROR("BTaggingEfficiencyTool::getInefficiencyScaleFactor call to getIndices failed " << flavour << " " << sfindex << " " << efindex);
1022  return CorrectionCode::Error;
1023  }
1024  Uncertainty unc=None;
1025  unsigned int unc_ind=0;
1026  if( m_applySyst) {
1027 
1028  unc = m_applyThisSyst.uncType;
1029  // if( m_applyThisSyst.isNamed) {
1030  // unc = SFNamed;
1031  // } else {
1032  // unc = SFEigen;
1033  // }
1034 
1035  if(!m_applyThisSyst.getIndex(flavour,unc_ind)) {
1036  ATH_MSG_VERBOSE("getInefficiencyScaleFactor: requested variation cannot be applied to flavour " << getLabel(flavour)
1037  << ", returning nominal result");
1038  unc = None;
1039  }
1040  }
1041 
1042  CalibrationStatus status = m_CDI->getInefficiencyScaleFactor(v,sfindex,efindex, unc, unc_ind, result, getLabel(flavour));
1043  // Interpret what has been retrieved;
1044  // this depends both on the uncertainty type and on the up/down setting.
1045  // For the Total uncertainty, note also the sign change compared to e.g. getScaleFactor().
1046  sf = result.first; // central value or up variation
1047  if (m_applySyst && unc != None) {
1048  if (! (unc == SFEigen || unc == SFNamed))
1049  sf += m_applyThisSyst.isUp ? -result.second : result.second ;
1050  else if (!m_applyThisSyst.isUp) {
1051  sf = result.second; // down variation
1052  }
1053  }
1054 
1055  switch (status) {
1056  case Analysis::kError:
1057  ATH_MSG_ERROR("BTaggingEfficiencyTool::getInefficiencyScaleFactor call to underlying code returned a kError!");
1058  return CorrectionCode::Error;
1059  case Analysis::kRange:
1061  return m_ignoreOutOfValidityRange ? CorrectionCode::Ok : CorrectionCode::OutOfValidityRange;
1062  case Analysis::kSuccess:
1063  default:
1064  return CorrectionCode::Ok;
1065  }
1066 }
1067 
1070 {
1071  if (! m_initialised) return CorrectionCode::Error;
1072 
1073  // get the btag label
1075 
1077  if (! fillVariables(jet, vars)) {
1078  ATH_MSG_ERROR("unable to fill variables required for scale factor evaluation");
1079  return CorrectionCode::Error;
1080  }
1081 
1082  return getMCEfficiency( flavour, vars, eff);
1083 }
1084 
1087  float & eff)
1088 {
1089  if (! m_initialised) return CorrectionCode::Error;
1091 
1092  unsigned int sfindex = 0;
1093  unsigned int efindex = 0;
1094 
1095  if( !getIndices(flavour,sfindex,efindex)) {
1096  ATH_MSG_ERROR("BTaggingEfficiencyTool::getMCEfficiency call to getIndices failed " << flavour << " " << sfindex << " " << efindex);
1097  return CorrectionCode::Error;
1098  }
1099  Uncertainty unc = None;
1100  // no uncertainty index here as there aren't any uncertainties associated with the MC efficiencies
1101  CalibrationStatus status = m_CDI->getMCEfficiency(v,efindex, unc,result);
1102  eff = result.first;
1103  if( m_applySyst && !m_applyThisSyst.isUp) {
1104  eff = result.second; // down variation
1105  }
1106 
1107  switch (status) {
1108  case Analysis::kError:
1109  ATH_MSG_ERROR("BTaggingEfficiencyTool::getMCEfficiency call to underlying code returned a kError!");
1110  return CorrectionCode::Error;
1111  case Analysis::kRange:
1113  return m_ignoreOutOfValidityRange ? CorrectionCode::Ok : CorrectionCode::OutOfValidityRange;
1114  case Analysis::kSuccess:
1115  default:
1116  return CorrectionCode::Ok;
1117  }
1118 }
1119 
1120 // get efficiencies with the onnx model (fixed cut wp)
1122 BTaggingEfficiencyTool::getMCEfficiencyONNX( const std::vector<std::vector<float>>& node_feat, std::vector<float>& effAllJet)
1123 {
1124  m_onnxUtil->runInference(node_feat, effAllJet);
1125  return CorrectionCode::Ok;
1126 }
1127 
1128 // get efficiencies with the onnx model (continuous wp)
1130 BTaggingEfficiencyTool::getMCEfficiencyONNX( const std::vector<std::vector<float>>& node_feat, std::vector<std::vector<float>>& effAllJetAllWp)
1131 {
1132  m_onnxUtil->runInference(node_feat, effAllJetAllWp);
1133  return CorrectionCode::Ok;
1134 }
1135 
1136 // Systematics framework - modelled on PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/Root/JetCalibrationToolExample3.cxx
1137 // returns true if the argument systematic is supported by this tool
1139 {
1141  return sys.find( systematic) != sys.end();
1142 }
1143 
1144 // this returns a list of systematics supported by this tool
1146  return m_systematics;
1147 }
1148 
1149 // subset of systematics that are recommended
1151  return affectingSystematics();
1152 }
1153 
1154 const std::map<SystematicVariation, std::vector<std::string> >
1156  std::map<SystematicVariation, std::vector<std::string> > results;
1157 
1158  if (! m_initialised) {
1159  ATH_MSG_ERROR("listSystematics() cannot be called before initialisation is finished");
1160  return results;
1161  }
1162 
1163 
1164  std::vector<unsigned int> all_flavours{5, 4, 15, 0};
1166  all_flavours = m_flex_label_integers;
1167  }
1168 
1169  for (const auto& info : m_systematicsInfo) {
1170  // The map key is easy...
1171  const SystematicVariation& variation = info.first;
1172  // Then see for which flavours this particular key is relevant
1173  std::vector<std::string> flavours;
1174  for(const unsigned int flavour : all_flavours){ // Grab the number 5,4,15,0 for B,C,T,Light respectively (or other custom labelings)
1175  unsigned int idx;
1176  if (info.second.getIndex(flavour, idx)){ // If the flavour is mapped to an index internally in the SystInfo.indexMap, then return true
1177  flavours.push_back(getLabel(int(flavour)));
1178  }
1179  }
1180  results[variation] = flavours; // <------ Map the list of flavours that a systematic applies to, to the SystematicVariation object that was retrieved from m_systematicsInfo
1181  }
1182  return results;
1183 }
1184 
1185 
1191 std::map<std::string, std::vector<std::string> >
1193  std::map<std::string, std::vector<std::string> > uncertainties;
1194 
1195  std::vector<unsigned int> all_flavours;
1197  all_flavours = { 5, 4, 15, 0 };
1198  } else {
1199  all_flavours = m_flex_label_integers;
1200  }
1201 
1202  for (const unsigned int flavourID : all_flavours){
1203  // Assumed model: use eigenvector variations. In this model, the tau SF are identical to the c-jet ones,
1204  // with merely one additional uncertainty assigned due to the extrapolation.
1205  unsigned int flavourIDRef = flavourID;
1206  if (m_using_conventional_labels and flavourID == 15){
1207  flavourIDRef = 4; // make C - T relationship
1208  }
1209  auto mapIter = m_SFIndices.find(flavourIDRef);
1210  if( mapIter==m_SFIndices.end()) { // if the flavour doesn't have an entry need to fail the initialization
1211  ATH_MSG_ERROR( "No entry for flavour " << flavourIDRef << " in SFIndices map, invalid initialization");
1212  continue;
1213  }
1214  int idRef = mapIter->second;
1215  // Retrieve the actual list
1216  std::vector<std::string> systematics = m_CDI->listScaleFactorUncertainties(idRef, getLabel(flavourID), named);
1217  // For the special case of tau SF, add the extrapolation from charm.
1218  // Since this comes on top of the charm uncertainties, it would always be a "named" uncertainty,
1219  // so there is no need to check for the "named" argument.
1220  if (m_using_conventional_labels and flavourID == 15) systematics.push_back("extrapolation from charm");
1221  uncertainties[getLabel(int(flavourID))] = systematics;
1222  }
1223  return uncertainties;
1224 }
1225 
1227 BTaggingEfficiencyTool::getEigenRecompositionCoefficientMap(const std::string &label, std::map<std::string, std::map<std::string, float>> & coefficientMap){
1228  // Calling EigenVectorRecomposition method in CDI and retrieve recomposition map.
1229  // If success, coefficientMap would be filled and return ok.
1230  // If failed, return error.
1231  // label : flavour label
1232  // coefficientMap: store returned coefficient map.
1233  if (! m_initialised) {
1234  ATH_MSG_ERROR("BTaggingEfficiencyTool has not been initialised");
1235  return CorrectionCode::Error;
1236  }
1237  if(label.compare("B") != 0 &&
1238  label.compare("C") != 0 &&
1239  label.compare("T") != 0 &&
1240  label.compare("Light") != 0){
1241  ATH_MSG_ERROR("Flavour label is illegal! Label need to be B,C,T or Light.");
1242  return CorrectionCode::Error;
1243  }
1244  CalibrationStatus status = m_CDI->runEigenVectorRecomposition(m_jetAuthor, label, m_OP);
1245  if (status != Analysis::kSuccess){
1246  ATH_MSG_ERROR("Failure running EigenVectorRecomposition Method.");
1247  return CorrectionCode::Error;
1248  }
1249  coefficientMap = m_CDI->getEigenVectorRecompositionCoefficientMap();
1250  return CorrectionCode::Ok;
1251 }
1252 
1253 // WARNING the behaviour of future calls to getEfficiency and friends are modified by this
1254 // method - it indicates which systematic shifts are to be applied for all future calls
1256  // If the user is doing the right thing, no need to use the costly filterForAffectingSystematics
1257  // i.e if only 1 variation passed and this variation is in the map. Else, resort to full logic.
1258  if (systConfig.size() == 1 ) {
1259  auto mapIter = m_systematicsInfo.find(*(systConfig.begin()));
1260  if (mapIter != m_systematicsInfo.end()) {
1261  m_applySyst = true;
1262  m_applyThisSyst = mapIter->second;
1263  ATH_MSG_VERBOSE("variation '" << systConfig.begin()->name() << "' applied successfully");
1264  return StatusCode::SUCCESS;
1265  }
1266  }
1267 
1268  // First filter out any systematics that do not apply to us
1269  SystematicSet filteredSysts;
1270  if (SystematicSet::filterForAffectingSystematics(systConfig, affectingSystematics(), filteredSysts) != StatusCode::SUCCESS) {
1271  ATH_MSG_ERROR("received unsupported systematics: " << systConfig.name());
1272  return StatusCode::FAILURE;
1273  }
1274  // check the size of the remaining (filtered) SystematicSet
1275  if (filteredSysts.size() == 0) {
1276  // If it is 0 then turn off systematics
1277  ATH_MSG_VERBOSE("empty systematics set; nothing to be done");
1278  m_applySyst = false;
1279  return StatusCode::SUCCESS;
1280  } else if (filteredSysts.size() > 1) {
1281  // Restriction: we allow only a single systematic variation affecting b-tagging
1282  ATH_MSG_WARNING("more than a single b-tagging systematic variation requested but not (yet) supported");
1283  return StatusCode::FAILURE;
1284  } else {
1285  // Interpret the (single) remaining variation
1286  SystematicVariation var = *(filteredSysts.begin());
1287  auto mapIter = m_systematicsInfo.find(var);
1288  if (mapIter == m_systematicsInfo.end()) {
1289  ATH_MSG_WARNING("variation '" << var.name() << "' not found! Cannot apply");
1290  return StatusCode::FAILURE;
1291  }
1292  m_applySyst = true;
1293  m_applyThisSyst = mapIter->second;
1294  ATH_MSG_VERBOSE("variation '" << var.name() << "' applied successfully");
1295  }
1296  return StatusCode::SUCCESS;
1297 }
1298 //
1299 
1300 bool
1302 {
1303  x.jetPt = jet.pt();
1304  x.jetEta = jet.eta();
1305  x.jetTagWeight = 0.;
1306  x.jetAuthor = m_jetAuthor;
1307  //bool weightOK = true;
1308 
1309  if (m_isContinuous2D){
1310  x.jetTagWeight = m_selectionTool->getQuantile(jet)+0.5;
1311  }
1312  else if (m_isContinuous) {
1314  if (!tagInfo) return false;
1315  // For now, we defer the tag weight computation to the selection tool only in the case of DL1* (this is likely to be revisited)
1316  if (m_taggerName.find("DL1") != std::string::npos || m_taggerName.find("GN1") != std::string::npos || m_taggerName.find("GN2") != std::string::npos) {
1318  } else {
1319  ATH_MSG_ERROR("BTaggingEfficiencyTool doesn't support tagger: "+m_taggerName);
1320  return CorrectionCode::Error;
1321  }
1322  }
1323 
1324  return true;
1325 }
1326 
1327 bool
1328 BTaggingEfficiencyTool::fillVariables( const double jetPt, const double jetEta, const double jetTagWeight, CalibrationDataVariables& x) const
1329 {
1330  x.jetPt = jetPt;
1331  x.jetEta = jetEta;
1332  x.jetTagWeight = jetTagWeight;
1333  x.jetAuthor = m_jetAuthor;
1334 
1335  return true;
1336 }
1337 
1338 // FIXME - if this method is kept - then need additional version that lets one pick the MapIndex by name - but this
1339 // would also mean a change in the CDI tool to retrieve the list of names
1340 // FIXME - this method might screw up the systematics framework by changing the list of valid systematics??? needs checking
1341 bool
1342 BTaggingEfficiencyTool::setMapIndex(const std::string& label, unsigned int index)
1343 {
1344  // do nothing unless it's needed!
1345  if (m_initialised && index == m_mapIndices[label]) return true;
1346  // convert to integer index
1347  unsigned int flavourID = -1; // set default, error if ever seen
1349  flavourID = getFlavourID(label);
1350  } else {
1351  auto iter = std::find(m_flex_labels.begin(), m_flex_labels.end(), label);
1352  if (iter != m_flex_labels.end()){
1353  flavourID = getFlavourID(label, false);
1354  }
1355  }
1356  // retrieve the new calibration index
1357  unsigned int effIndex;
1358  if (m_CDI->retrieveCalibrationIndex(label, m_OP, m_jetAuthor, false, effIndex, index)) {
1359  // replace cached information
1360  m_mapIndices[label] = index;
1361  m_EffIndices[flavourID] = effIndex; // This shortcuts you from flavourID to Eff container
1362  unsigned int sfIndex;
1363  if( m_CDI->retrieveCalibrationIndex(label, m_OP, m_jetAuthor, true, sfIndex, index)) {
1364  m_SFIndices[flavourID] = sfIndex; // This shortcuts you from flavourID to SF container
1365  return true;
1366  } else {
1367  ATH_MSG_ERROR("setMapIndex failed to find a SF calibration object" << label << " " << index);
1368  }
1369  } else {
1370  // flag non-existent calibration object & do nothing
1371  ATH_MSG_ERROR("setMapIndex failed to find an Eff calibration object" << label << " " << index);
1372  }
1373  return false;
1374 }
1376 
1377  if(m_DSID_to_MapIndex.find(dsid) == m_DSID_to_MapIndex.end() ){
1378  ATH_MSG_WARNING("setMapIndex DSID " << dsid << "not found in config file");
1379 
1380  }else{
1381  unsigned int map_index = m_DSID_to_MapIndex[dsid];
1382 
1383  bool set_b = setMapIndex("B",map_index);
1384  bool set_c = setMapIndex("C",map_index);
1385  bool set_light = setMapIndex("Light",map_index);
1386  bool set_t = setMapIndex("T",map_index);
1387 
1388  return set_b && set_c && set_light && set_t;
1389  }
1390 
1391 
1392  return false;
1393 
1394 }
1395 
1396 // private method to generate the list of eigenvector variations
1397 // internally these are not named, they are just numbered
1398 // but the systematics framework needs names
1399 std::vector<std::string> BTaggingEfficiencyTool::makeEigenSyst(const std::string & flav, int number, const std::string& suffix) {
1400  std::vector<std::string> systStrings;
1401  for(int i=0;i<number;++i) {
1402  std::ostringstream ost;
1403  ost << flav << "_" << i << suffix;
1404  std::string basename="FT_EFF_Eigen_"+ost.str();
1405  systStrings.push_back(basename);
1406  }
1407  return systStrings;
1408 }
1409 
1410 bool
1411 BTaggingEfficiencyTool::getIndices(unsigned int flavour, unsigned int & sf, unsigned int & ef) const {
1412  auto mapIter = m_SFIndices.find(flavour);
1413  if(mapIter != m_SFIndices.end()) {
1414  sf = mapIter->second;
1415  } else {
1416  return false;
1417  }
1418 
1419  mapIter = m_EffIndices.find(flavour);
1420  if(mapIter != m_EffIndices.end()) {
1421  ef = mapIter->second;
1422  } else {
1423  return false;
1424  }
1425  return true;
1426 }
1427 
1428 bool
1429 BTaggingEfficiencyTool::SystInfo::getIndex( unsigned int flavourID, unsigned int & index) const {
1430  auto mapIter = indexMap.find(flavourID); // if this systematic applies to flavour (i.e. if it's found) then return the index of the variation (numVariation) internal to CDIROOT
1431  if (mapIter==indexMap.end()) {
1432  return false;
1433  } else {
1434  index = mapIter->second;
1435  return true;
1436  }
1437 }
1438 
1439 // helper method to take a list of systematic names and a flavour and add them to the map of SystematicVariation to SystInfo
1440 // this map is used to do the lookup of which systematic to apply.
1441 // ie it is used to map the systematics framework on the systematics approach of the CDI
1442 
1443 bool BTaggingEfficiencyTool::addSystematics(const std::vector<std::string> & systematicNames, unsigned int flavourID, Uncertainty uncType) {
1444  for (int i=0, n=systematicNames.size(); i<n; ++i) {
1445  const std::string systName = systematicNames[i];
1447  SystematicVariation down(systName,-1);
1449  if (iter == m_systematicsInfo.end()) {
1450  // First case: new variation
1451  SystInfo info;
1452  info.isUp = true;
1453  info.uncType = uncType;
1454  info.indexMap[flavourID] = i;
1456  ATH_MSG_VERBOSE("addSystematics: adding " << systName << " for flavour " << getLabel(flavourID));
1457  info.isUp = false;
1458  m_systematicsInfo[down]=info;
1459  } else {
1460  // Second case: already known variation. This can happen if a variation applies to more than one
1461  // jet flavour. Check that indeed it's not registered yet for the requested flavour.
1462  SystInfo info = iter->second; // make a copy
1463  std::map<unsigned int, unsigned int>::const_iterator indIter = info.indexMap.find(flavourID);
1464  if (indIter != info.indexMap.end()) {
1465  ATH_MSG_ERROR("addSystematics : flavourID " << flavourID << " is already in the map for uncertainty '" << systName << "', ignoring");
1466  continue;
1467  } else {
1468  info.indexMap[flavourID] = i;
1470  ATH_MSG_VERBOSE("addSystematics: adding " << systName << " for flavour " << getLabel(flavourID));
1471  info.isUp = false;
1472  m_systematicsInfo[down] = info;
1473  }
1474  }
1475  }
1476  return true;
1477 }
grepfile.info
info
Definition: grepfile.py:38
Analysis::CalibResult
std::pair< double, double > CalibResult
Definition: CalibrationDataInterfaceBase.h:34
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
python.Dso.registry
registry
Definition: Control/AthenaServices/python/Dso.py:159
BTaggingUtilities.h
BTaggingEfficiencyTool::getLabel
std::string getLabel(int flavourID) const
convert integer flavour index to its string equivalent
Definition: BTaggingEfficiencyTool.h:242
beamspotnt.var
var
Definition: bin/beamspotnt.py:1394
BTaggingEfficiencyTool::m_isContinuous2D
bool m_isContinuous2D
Definition: BTaggingEfficiencyTool.h:400
BTaggingEfficiencyTool::m_EffFile
std::string m_EffFile
name of the optional MC efficiency file (may be changed by the PathResolver)
Definition: BTaggingEfficiencyTool.h:326
BTaggingEfficiencyTool::m_mapIndices
std::map< std::string, unsigned int > m_mapIndices
Definition: BTaggingEfficiencyTool.h:405
python.trigbs_prescaleL1.ost
ost
Definition: trigbs_prescaleL1.py:104
get_generator_info.result
result
Definition: get_generator_info.py:21
hotSpotInTAG.suffix
string suffix
Definition: hotSpotInTAG.py:186
BTaggingEfficiencyTool::m_SFName_flex
std::string m_SFName_flex
Definition: BTaggingEfficiencyTool.h:342
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
BTagging.h
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
BTaggingEfficiencyTool::m_ignoreOutOfValidityRange
bool m_ignoreOutOfValidityRange
if true, ignore out-of-extrapolation range errors (i.e., return CorrectionCode::Ok if these are encou...
Definition: BTaggingEfficiencyTool.h:370
BTaggingEfficiencyTool::m_DSID_to_MapIndex
std::map< unsigned int, unsigned int > m_DSID_to_MapIndex
Definition: BTaggingEfficiencyTool.h:413
BTaggingEfficiencyTool::m_uncertaintySuffixes_flex
std::string m_uncertaintySuffixes_flex
Definition: BTaggingEfficiencyTool.h:345
BTaggingEfficiencyTool::getIndices
bool getIndices(unsigned int flavour, unsigned int &sf, unsigned int &ef) const
helper function for retrieving object indices
Definition: BTaggingEfficiencyTool.cxx:1411
asg::AnaToolHandle::retrieve
StatusCode retrieve()
initialize the tool
BTaggingEfficiencyTool::m_excludeFromEV
std::string m_excludeFromEV
semicolon-separated list of uncertainties to be excluded from the eigenvector variation procedure for...
Definition: BTaggingEfficiencyTool.h:335
trim
std::string trim(const std::string &str, const std::string &whitespace=" \t")
Definition: BTaggingTruthTaggingTool.cxx:1149
CDIReader.h
BTaggingEfficiencyTool::getMCEfficiencyONNX
CP::CorrectionCode getMCEfficiencyONNX(const std::vector< std::vector< float >> &node_feat, std::vector< float > &effAllJet)
Computes the MC efficiency of the jets in a given event.
Definition: BTaggingEfficiencyTool.cxx:1122
CalibrationDataContainer.h
CP::SystematicSet::size
size_t size() const
returns: size of the set
Definition: SystematicSet.h:71
index
Definition: index.py:1
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
Analysis::SFNamed
@ SFNamed
Definition: CalibrationDataInterfaceROOT.h:70
PlotCalibFromCool.label
label
Definition: PlotCalibFromCool.py:78
BTaggingEfficiencyTool.h
BTaggingEfficiencyTool::getEigenRecompositionCoefficientMap
CP::CorrectionCode getEigenRecompositionCoefficientMap(const std::string &label, std::map< std::string, std::map< std::string, float >> &coefficientMap)
Run EigenvectorRecomposition method and get the coefficient map.
Definition: BTaggingEfficiencyTool.cxx:1227
BTaggingEfficiencyTool::m_useCTag
bool m_useCTag
if false, suppress any non-error/warning printout from the underlying tool 1D tagging only: define we...
Definition: BTaggingEfficiencyTool.h:373
BTaggingEfficiencyTool::makeEigenSyst
std::vector< std::string > makeEigenSyst(const std::string &flav, int number, const std::string &suffix)
generate names for the eigenvector variations for the given jet flavour
Definition: BTaggingEfficiencyTool.cxx:1399
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
asg::AnaToolHandle::setTypeAndName
void setTypeAndName(const std::string &val_typeAndName)
set the value of type and name
skel.it
it
Definition: skel.GENtoEVGEN.py:423
asg
Definition: DataHandleTestTool.h:28
CP::SystematicSet
Class to wrap a set of SystematicVariations.
Definition: SystematicSet.h:31
BTaggingEfficiencyTool::SystInfo::getIndex
bool getIndex(unsigned int flavourID, unsigned int &index) const
Definition: BTaggingEfficiencyTool.cxx:1429
BTaggingEfficiencyTool::m_initialised
bool m_initialised
flag to indicate tool is initialized correctly when set
Definition: BTaggingEfficiencyTool.h:388
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
CP::SystematicSet::name
std::string name() const
returns: the systematics joined into a single string.
Definition: SystematicSet.cxx:278
BTaggingEfficiencyTool::getEfficiency
CP::CorrectionCode getEfficiency(const xAOD::Jet &jet, float &eff)
Computes the data efficiency for the given jet.
Definition: BTaggingEfficiencyTool.cxx:841
IBTaggingSelectionTool::getTaggerWeight
virtual CP::CorrectionCode getTaggerWeight(const xAOD::Jet &jet, double &tagweight) const =0
BTaggingEfficiencyTool::m_EffNames_flex
std::string m_EffNames_flex
Definition: BTaggingEfficiencyTool.h:344
TrigInDetValidation_Base.test
test
Definition: TrigInDetValidation_Base.py:144
BTaggingEfficiencyTool::listSystematics
const std::map< CP::SystematicVariation, std::vector< std::string > > listSystematics() const
Definition: BTaggingEfficiencyTool.cxx:1155
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
BTaggingEfficiencyTool::m_systematics
CP::SystematicSet m_systematics
Definition: BTaggingEfficiencyTool.h:396
CP::SystematicVariation
Definition: SystematicVariation.h:47
CalibrationDataVariables.h
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:40
asg::AnaToolHandle::setProperty
StatusCode setProperty(const std::string &property, const T2 &value)
set the given property of the tool.
x
#define x
BTaggingEfficiencyTool::m_extFlavourLabel
bool m_extFlavourLabel
if true, use an 'extended' labelling (allowing for multiple HF hadrons -or perhaps partons- in the je...
Definition: BTaggingEfficiencyTool.h:363
Analysis::TauExtrapolation
@ TauExtrapolation
Definition: CalibrationDataInterfaceROOT.h:70
mapkey::sys
@ sys
Definition: TElectronEfficiencyCorrectionTool.cxx:42
asg::AnaToolHandle::declarePropertyFor
void declarePropertyFor(T2 *tool, const std::string &name, const std::string &description="")
declare as property on the given tool
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
BTaggingEfficiencyTool::addSystematics
bool addSystematics(const std::vector< std::string > &systematicNames, unsigned int flavourID, Analysis::Uncertainty uncType)
add entries to the systematics registry
Definition: BTaggingEfficiencyTool.cxx:1443
BTaggingEfficiencyTool::initialize
StatusCode initialize()
Initialise the tool.
Definition: BTaggingEfficiencyTool.cxx:213
Analysis::kSuccess
@ kSuccess
Definition: CalibrationDataVariables.h:57
BTaggingEfficiencyTool::m_isContinuous
bool m_isContinuous
Definition: BTaggingEfficiencyTool.h:398
Analysis::Total
@ Total
Definition: CalibrationDataInterfaceROOT.h:70
BTaggingEfficiencyTool::m_EffNames
std::map< std::string, std::string > m_EffNames
semicolon-separated lists of MC efficiency parametrisation names
Definition: BTaggingEfficiencyTool.h:333
xAOD::ExclusiveConeHadronFlavourLabel
int ExclusiveConeHadronFlavourLabel(const xAOD::Jet *jet)
Definition: JetFlavourInfo.cxx:74
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
BTaggingEfficiencyTool::m_EffIndices
std::map< unsigned int, unsigned int > m_EffIndices
actual information identifying efficiency calibration objects
Definition: BTaggingEfficiencyTool.h:410
BTaggingEfficiencyTool::SystInfo::indexMap
std::map< unsigned int, unsigned int > indexMap
Definition: BTaggingEfficiencyTool.h:225
BTaggingEfficiencyTool::m_useDevFile
bool m_useDevFile
if true, attempt to retrieve the data/MC efficiency scale factor calibration files from the @PathReso...
Definition: BTaggingEfficiencyTool.h:359
CalibrationDataInterfaceROOT.h
xAOD::jetFlavourLabel
int jetFlavourLabel(const xAOD::Jet *jet, JetFlavourLabelType=ExclConeHadron)
Definition: JetFlavourInfo.cxx:93
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
BTaggingEfficiencyTool::getMCEfficiency
CP::CorrectionCode getMCEfficiency(const xAOD::Jet &jet, float &eff)
Computes the MC efficiency for the given jet.
Definition: BTaggingEfficiencyTool.cxx:1069
BTaggingEfficiencyTool::m_applySyst
bool m_applySyst
Definition: BTaggingEfficiencyTool.h:391
Analysis::kExtrapolatedRange
@ kExtrapolatedRange
Definition: CalibrationDataVariables.h:59
lumiFormat.i
int i
Definition: lumiFormat.py:92
SystematicRegistry.h
BTaggingEfficiencyTool::getFlavourID
unsigned int getFlavourID(const std::string &label, bool conventional=true) const
convert string flavour to its integer index equivalent
Definition: BTaggingEfficiencyTool.h:271
beamspotman.n
n
Definition: beamspotman.py:731
Generate_dsid_ranseed.dsid
dsid
Definition: Generate_dsid_ranseed.py:6
Analysis::Uncertainty
Uncertainty
specification of type information requested by the user
Definition: CalibrationDataInterfaceROOT.h:70
Analysis::Medium
@ Medium
Definition: CalibrationDataInterfaceROOT.h:73
Analysis::kError
@ kError
Definition: CalibrationDataVariables.h:60
OnnxUtil.h
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.sizes.location
string location
Definition: sizes.py:11
BTaggingEfficiencyTool::m_jetAuthor
std::string m_jetAuthor
jet collection name
Definition: BTaggingEfficiencyTool.h:353
BTaggingEfficiencyTool::m_SFIndices
std::map< unsigned int, unsigned int > m_SFIndices
actual information identifying scale factor calibration objects
Definition: BTaggingEfficiencyTool.h:408
Analysis::Loose
@ Loose
Definition: CalibrationDataInterfaceROOT.h:73
CalibCoolCompareRT.up
up
Definition: CalibCoolCompareRT.py:109
LHEF::Reader
Pythia8::Reader Reader
Definition: Prophecy4fMerger.cxx:11
Analysis::kRange
@ kRange
Definition: CalibrationDataVariables.h:58
Analysis::SFEigen
@ SFEigen
Definition: CalibrationDataInterfaceROOT.h:70
BTaggingEfficiencyTool::setMapIndex
bool setMapIndex(const std::string &flavour, unsigned int index)
Specify the "map index" to be used for the given jet flavour (at initialisation time it will be set t...
Definition: BTaggingEfficiencyTool.cxx:1342
BTaggingEfficiencyTool::listScaleFactorSystematics
std::map< std::string, std::vector< std::string > > listScaleFactorSystematics(bool named=false) const
This merely passes on the request to the underlying CDI object (listSystematics() cannot be used here...
Definition: BTaggingEfficiencyTool.cxx:1192
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
BTaggingEfficiencyTool::m_using_conventional_labels
bool m_using_conventional_labels
Definition: BTaggingEfficiencyTool.h:341
BTaggingEfficiencyTool::m_oldConeFlavourLabel
bool m_oldConeFlavourLabel
when using cone-based labelling (see above), if true, use the "traditional" (parton-based) labelling ...
Definition: BTaggingEfficiencyTool.h:365
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
BTaggingEfficiencyTool::m_flex_label_integers
std::vector< unsigned int > m_flex_label_integers
Definition: BTaggingEfficiencyTool.h:382
xAOD::BTagging_v1
Definition: BTagging_v1.h:39
BTaggingEfficiencyTool::recommendedSystematics
CP::SystematicSet recommendedSystematics() const
Return a list of "recommended" systematic variations supported by this tool.
Definition: BTaggingEfficiencyTool.cxx:1150
RivetAnalysis_JO.systName
def systName
Definition: RivetAnalysis_JO.py:32
xAOD::ConeFinalPartonFlavourLabel
int ConeFinalPartonFlavourLabel(const xAOD::Jet *jet)
Definition: JetFlavourInfo.cxx:62
BTaggingEfficiencyTool::fillVariables
bool fillVariables(const xAOD::Jet &jet, Analysis::CalibrationDataVariables &x) const
Fill the Analysis::CalibrationDataVariables struct with relevant information pertaining to the jet co...
Definition: BTaggingEfficiencyTool.cxx:1301
BTaggingEfficiencyTool::~BTaggingEfficiencyTool
virtual ~BTaggingEfficiencyTool()
Create a constructor for standalone usage.
Definition: BTaggingEfficiencyTool.cxx:209
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
BTaggingEfficiencyTool::SystInfo::uncType
Analysis::Uncertainty uncType
Definition: BTaggingEfficiencyTool.h:226
BTaggingEfficiencyTool::applySystematicVariation
StatusCode applySystematicVariation(const CP::SystematicSet &set)
Set the tool to return "shifted" values.
Definition: BTaggingEfficiencyTool.cxx:1255
BTaggingEfficiencyTool::isAffectedBySystematic
bool isAffectedBySystematic(const CP::SystematicVariation &systematic) const
Returns whether or not the given systematic variation is supported by this tool.
Definition: BTaggingEfficiencyTool.cxx:1138
PathResolver.h
CheckAppliedSFs.systematics
def systematics
Definition: CheckAppliedSFs.py:231
Analysis::CalibrationStatus
CalibrationStatus
Definition: CalibrationDataVariables.h:56
CP::SystematicSet::insert
void insert(const SystematicVariation &systematic)
description: insert a systematic into the set
Definition: SystematicSet.cxx:88
python.selection.number
number
Definition: selection.py:20
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
TrackCorrType::None
@ None
BTaggingEfficiencyTool::m_systematicsInfo
std::map< CP::SystematicVariation, SystInfo > m_systematicsInfo
Definition: BTaggingEfficiencyTool.h:394
python.ami.results
def results
Definition: ami.py:386
BTaggingEfficiencyTool::m_uncertaintySuffixes
std::map< std::string, std::string > m_uncertaintySuffixes
optional (per-flavour) suffix that can be used to decorrelate uncertainties (between flavours,...
Definition: BTaggingEfficiencyTool.h:339
BTaggingEfficiencyTool::m_minPt
float m_minPt
minimum jet pT
Definition: BTaggingEfficiencyTool.h:355
BTaggingEfficiencyTool::m_pathToONNX
std::string m_pathToONNX
if this string is empty, the onnx tool won't be created
Definition: BTaggingEfficiencyTool.h:375
BTaggingEfficiencyTool::m_selectionTool
asg::AnaToolHandle< IBTaggingSelectionTool > m_selectionTool
we need access to a BTaggingSelectionTool, at least for DL1 weight computation
Definition: BTaggingEfficiencyTool.h:320
IBTaggingSelectionTool::getQuantile
virtual int getQuantile(const xAOD::IParticle *) const =0
Decide in which quantile of the tagger weight distribution the jet belongs The return value represent...
BTaggingEfficiencyTool::getInefficiencyScaleFactor
CP::CorrectionCode getInefficiencyScaleFactor(const xAOD::Jet &jet, float &sf)
Computes the data/MC inefficiency scale factor for the given jet.
Definition: BTaggingEfficiencyTool.cxx:993
BTaggingEfficiencyTool::m_SFFile
std::string m_SFFile
name of the data/MC efficiency scale factor calibration file (may be changed by the PathResolver)
Definition: BTaggingEfficiencyTool.h:323
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
xAOD::BTaggingUtilities::getBTagging
const BTagging * getBTagging(const SG::AuxElement &part)
Access the default xAOD::BTagging object associated to an object.
Definition: BTaggingUtilities.cxx:37
BTaggingEfficiencyTool::m_onnxUtil
std::unique_ptr< OnnxUtil > m_onnxUtil
pointer to the onnx tool
Definition: BTaggingEfficiencyTool.h:314
python.PyAthena.v
v
Definition: PyAthena.py:157
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
CP::CorrectionCode::Ok
@ Ok
The correction was done successfully.
Definition: CorrectionCode.h:38
DeMoScan.index
string index
Definition: DeMoScan.py:362
BTaggingEfficiencyTool::BTaggingEfficiencyTool
BTaggingEfficiencyTool(const std::string &name)
Create a proper constructor for Athena.
Definition: BTaggingEfficiencyTool.cxx:150
BTaggingEfficiencyTool::getInefficiency
CP::CorrectionCode getInefficiency(const xAOD::Jet &jet, float &eff)
Computes the data inefficiency for the given jet.
Definition: BTaggingEfficiencyTool.cxx:917
python.CaloScaleNoiseConfig.str
str
Definition: CaloScaleNoiseConfig.py:78
BTaggingEfficiencyTool::m_applyThisSyst
SystInfo m_applyThisSyst
Definition: BTaggingEfficiencyTool.h:392
mapkey::sf
@ sf
Definition: TElectronEfficiencyCorrectionTool.cxx:38
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
xAOD::GAFinalHadronFlavourLabel
int GAFinalHadronFlavourLabel(const xAOD::Jet *jet)
Definition: JetFlavourInfo.cxx:14
Analysis::CalibrationDataInterfaceROOT
Definition: CalibrationDataInterfaceROOT.h:88
BTaggingEfficiencyTool::m_useRecommendedEVExclusions
bool m_useRecommendedEVExclusions
if true, extract pre-set lists of uncertainties to be recommended from the EV decomposition (in addit...
Definition: BTaggingEfficiencyTool.h:368
CP::SystematicRegistry
This module implements the central registry for handling systematic uncertainties with CP tools.
Definition: SystematicRegistry.h:25
Analysis::SFGlobalEigen
@ SFGlobalEigen
Definition: CalibrationDataInterfaceROOT.h:70
CP::SystematicSet::begin
const_iterator begin() const
description: const iterator to the beginning of the set
Definition: SystematicSet.h:55
BTaggingEfficiencyTool::SystInfo::isUp
bool isUp
Definition: BTaggingEfficiencyTool.h:228
DEBUG
#define DEBUG
Definition: page_access.h:11
BTaggingEfficiencyTool::getScaleFactor
CP::CorrectionCode getScaleFactor(const xAOD::Jet &jet, float &sf)
Computes the data/MC efficiency scale factor for the given jet.
Definition: BTaggingEfficiencyTool.cxx:753
Analysis::CalibrationDataVariables
Definition: CalibrationDataVariables.h:42
CP::CorrectionCode
Return value from object correction CP tools.
Definition: CorrectionCode.h:31
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
BTaggingEfficiencyTool::m_EVReduction
std::map< std::string, std::string > m_EVReduction
specification of the eigenvector reduction strategy (if eigenvectors are used)
Definition: BTaggingEfficiencyTool.h:331
BTaggingEfficiencyTool::m_CDI
std::shared_ptr< Analysis::CalibrationDataInterfaceROOT > m_CDI
pointer to the object doing the actual work
Definition: BTaggingEfficiencyTool.h:312
BTaggingEfficiencyTool::m_excludeFlvFromEV_flex
std::string m_excludeFlvFromEV_flex
Definition: BTaggingEfficiencyTool.h:346
Analysis::None
@ None
Definition: CalibrationDataInterfaceROOT.h:70
dqt_zlumi_alleff_HIST.eff
int eff
Definition: dqt_zlumi_alleff_HIST.py:113
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
str
Definition: BTagTrackIpAccessor.cxx:11
BTaggingEfficiencyTool::m_systStrategy
std::string m_systStrategy
systematics model to be used (current choices are "SFEigen", "SFEigenRefined", and "Envelope") // <--...
Definition: BTaggingEfficiencyTool.h:357
merge.status
status
Definition: merge.py:17
BTaggingEfficiencyTool::m_OP
std::string m_OP
operating point
Definition: BTaggingEfficiencyTool.h:351
BTaggingEfficiencyTool::m_flex_labels
std::vector< std::string > m_flex_labels
Definition: BTaggingEfficiencyTool.h:381
BTaggingEfficiencyTool::m_SFNames
std::map< std::string, std::string > m_SFNames
names of the data/MC scale factor calibrations
Definition: BTaggingEfficiencyTool.h:329
BTaggingEfficiencyTool::affectingSystematics
CP::SystematicSet affectingSystematics() const
Return a list of all systematic variations supported by this tool.
Definition: BTaggingEfficiencyTool.cxx:1145
Analysis::Tight
@ Tight
Definition: CalibrationDataInterfaceROOT.h:73
Analysis::CDIReader
Definition: CDIReader.h:39
BTaggingEfficiencyTool::m_EVReduction_flex
std::string m_EVReduction_flex
Definition: BTaggingEfficiencyTool.h:343
Analysis::Extrapolation
@ Extrapolation
Definition: CalibrationDataInterfaceROOT.h:70
BTaggingEfficiencyTool::m_excludeFlvFromEV
std::map< std::string, std::string > m_excludeFlvFromEV
semicolon-separated list of uncertainties to be excluded from the eigenvector variation procedure for...
Definition: BTaggingEfficiencyTool.h:337
BTaggingEfficiencyTool::m_useFlex
bool m_useFlex
Definition: BTaggingEfficiencyTool.h:379
IParticle
Definition: Event/EventKernel/EventKernel/IParticle.h:43
python.compressB64.c
def c
Definition: compressB64.py:93
BTaggingEfficiencyTool::m_doXbbTagging
bool m_doXbbTagging
Definition: BTaggingEfficiencyTool.h:380
BTaggingEfficiencyTool::SystInfo
Definition: BTaggingEfficiencyTool.h:223
BTaggingEfficiencyTool::m_taggerName
std::string m_taggerName
tagger name
Definition: BTaggingEfficiencyTool.h:349
BTaggingEfficiencyTool::m_SFFileFull
std::string m_SFFileFull
Definition: BTaggingEfficiencyTool.h:324
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
LheEventFiller_Common.ef
ef
Definition: SFGen_i/share/common/LheEventFiller_Common.py:7
BTaggingEfficiencyTool::m_coneFlavourLabel
bool m_coneFlavourLabel
if true, use cone-based labelling (as opposed to ghost association)
Definition: BTaggingEfficiencyTool.h:361
BTaggingEfficiencyTool::m_EffConfigFile
std::string m_EffConfigFile
Definition: BTaggingEfficiencyTool.h:327
beamspotman.basename
basename
Definition: beamspotman.py:640