ATLAS Offline Software
Database.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
9 
10 #include <fstream>
11 #include <sstream>
12 #include <algorithm>
13 #include <regex>
14 #include <limits>
15 #include <functional>
16 #include <cmath>
17 
18 #include "TFile.h"
19 #include "TKey.h"
20 #include "TH1.h"
21 #include "TH2.h"
22 
23 using namespace FakeBkgTools;
24 using namespace CP;
25 
26 Database::Database(Client client, bool useGeV, bool convertWhenMissing) :
27  m_useGeV(useGeV),
28  m_typesToFill(selectTypesToFill(client)),
29  m_convertWhenMissing(convertWhenMissing)
30 {
31  reset();
32 }
33 
35 {
36  m_tables.clear();
37  m_systs.clear();
38  m_stats.clear();
39  m_params.clear();
44 }
45 
46 bool Database::ready() const
47 {
49  for(auto& kv : m_tables)
50  {
51  if(kv.second.size()) return true;
52  }
53  return false;
54 }
55 
57 {
58  for(auto& param : m_params)
59  {
60  if(param.level == Param::Level::EVENT) return true;
61  }
62  return false;
63 }
64 
65 bool Database::fillEfficiencies(ParticleData& pd, const xAOD::IParticle& p, const xAOD::EventInfo& eventInfo, std::string& error) const
66 {
67  std::map<unsigned, EfficiencyTable::BoundType> cachedParamVals;
69  for(int wt=0;wt<N_EFFICIENCY_TYPES;++wt)
70  {
71  EfficiencyType wantedType = static_cast<EfficiencyType>(wt);
72  if(!m_typesToFill[wantedType]) continue;
73  Efficiency* eff = selectEfficiency(pd, p, wantedType);
74  if(!eff) continue;
75 
77  EfficiencyType type = getSourceType(wantedType);
78 
79  bool found_central = false;
80  eff->nominal = 1.f;
81  eff->uncertainties.clear();
82 
83  auto relevantTables = m_tables.find(type);
84  if(relevantTables == m_tables.end())
85  {
86  error = "missing table for " + getTypeAsString(type);
87  return false;
88  }
89 
91  for(auto& table : relevantTables->second)
92  {
93  int status = readEfficiencyFromTable(*eff, table, cachedParamVals, p, eventInfo, error);
94  if(status < 0) return false;
95  if(status == 1)
96  {
97  if(found_central)
98  {
99  error = "while retrieving " + getTypeAsString(type) + ", found two non-orthogonal tables providing the central value";
100  return false;
101  }
102  found_central = true;
103  }
104  }
105  if(!found_central)
106  {
107  error = "didn't find central value for " + getTypeAsString(type);
108  return false;
109  }
111  if(type != wantedType)
112  {
113  if(eff == &pd.fake_factor)
114  {
115  float f = eff->nominal/(1.f-eff->nominal), k = pow(f/eff->nominal, 2);
116  eff->nominal = f;
117  for(auto& kv : eff->uncertainties) kv.second *= k;
118  }
119  else if(eff == &pd.fake_efficiency)
120  {
121  float e = eff->nominal/(1.f+eff->nominal), k = pow(e/eff->nominal, 2);
122  eff->nominal = e;
123  for(auto& kv : eff->uncertainties) kv.second *= k;
124  }
125  }
126  }
127  return true;
128 }
129 
130 int Database::readEfficiencyFromTable(Efficiency& eff, const EfficiencyTable& table, std::map<unsigned, EfficiencyTable::BoundType>& cachedParamVals, const xAOD::IParticle& p, const xAOD::EventInfo& eventInfo, std::string& error) const
131 {
133  int bin = 0;
134  for(const auto& dim : table.m_dimensions)
135  {
136  auto& param = m_params[dim.paramUID];
137  auto ins = cachedParamVals.emplace(dim.paramUID, EfficiencyTable::BoundType{});
138  auto& val = ins.first->second;
139  if(ins.second)
140  {
141  if(!retrieveParameterValue(p, eventInfo, param, val))
142  {
143  error = "can't retrieve value of parameter \"" + param.name + "\"";
144  return -1;
145  }
146  }
147  auto first = table.m_bounds.begin()+dim.iMinBound, last = first+dim.nBounds;
148  auto ubound = std::upper_bound(first, last, val,
149  [=](auto x, auto y){ return param.integer() ? (x.as_int<y.as_int) : (x.as_float<y.as_float); });
150  if(ubound==first || ubound==last)
151  {
152  bin = -1;
153  break;
154  }
155  bin = bin * (dim.nBounds-1) + (ubound - first - 1);
156  }
157  if(bin < 0) return 0;
158 
160  if(table.inputType != InputType::CENTRAL_VALUE && table.inputType != InputType::CORRECTION)
161  {
162  error = "unknown table type (tool implementation incomplete!)";
163  return -1;
164  }
165  auto& ref = table.m_efficiencies[bin];
166  for(auto& kv : eff.uncertainties) kv.second *= ref.nominal;
167  for(auto& kv : ref.uncertainties)
168  {
170  {
171  if(!eff.uncertainties.emplace(kv.first, eff.nominal*kv.second).second)
172  {
173  error = "central values and corrections must use different systematic uncertainties";
174  return -1;
175  }
176  }
177  }
178  eff.nominal *= ref.nominal;
179  return (table.inputType==InputType::CENTRAL_VALUE)? 1 : 2;
180 }
181 
182 /*
183  * Loading from XML
184  */
185 
186 void Database::importXML(std::string filename)
187 {
189 
190  std::ifstream xml;
191  xml.open(filename, std::ios_base::binary);
192  auto begpos = xml.tellg();
193  xml.seekg(0, std::ios_base::end);
194  std::size_t bufferSize = 1.05 * static_cast<std::size_t>(xml.tellg() - begpos);
196  if(bufferSize > 0x100000) bufferSize = 0x100000;
197  xml.close();
198 
199  xml.open(filename, std::ios_base::in);
200  if(!xml.is_open()) throw(GenericError() << "unable to open file " << filename);
201 
202  std::string line;
203  m_xmlBuffer.reserve(bufferSize);
204  m_lineOffset.clear();
205  m_lineOffset.push_back(0);
206  while(std::getline(xml, line))
207  {
208  while(line.length() && (line.back()=='\n' || line.back()=='\r')) line.pop_back();
209  m_xmlBuffer += line + ' ';
210  m_lineOffset.push_back(m_xmlBuffer.length());
211  }
212  xml.close();
213 
216 
219  StringRef stream(m_xmlBuffer.data(), m_xmlBuffer.length()), contents, tag;
220  while(stream.length())
221  {
223  if(tag=="electron" || tag=="muon" || tag=="tau") addTables(tag, attributes, contents);
224  else if(tag=="param") addParams(tag, contents, attributes);
225  else if(tag=="syst") addSysts(tag, contents, attributes);
226  else if(tag=="ROOT") importCustomROOT(tag, contents, attributes);
227  else throw(XmlError(stream) << "unknown/unexpected XML tag \"" << tag.str() << "\"");
228  }
229  m_lineOffset.clear();
230  m_lineOffset.shrink_to_fit();
231  m_xmlBuffer.clear();
232  m_xmlBuffer.shrink_to_fit();
233 }
234 
236 {
237  tag.clear();
238  contents.clear();
239  for(auto& kv : attributes) kv.second.clear();
241  std::string pattern = "^\\s*(<([[:alnum:]]+)((?:\\s+\\|?[_[:alnum:]]+\\|?\\s*=\\s*\"[_[:alnum:]\\s,-\\[\\]\\.\\|]+\")*)\\s*>)(.*?)</\\2>\\s*";
242  std::cmatch cmr;
243  if(!std::regex_search(stream.ptr, stream.endptr, cmr, std::regex(pattern)))
244  {
246  throw(XmlError(stream) << "unable to find next tag");
247  }
248  tag.set(stream.ptr+cmr.position(2), cmr.length(2));
249 
250  readTagAttributes(StringRef(stream.ptr+cmr.position(3), cmr.length(3)), tag.str(), attributes);
251 
252  auto cpos = cmr.size()-1;
253  contents.set(stream.ptr+cmr.position(cpos), cmr.length(cpos));
254 
255  stream.ptr += cmr.length();
256 }
257 
259 {
260  auto nAttr = std::count(stream.ptr, stream.endptr, '=');
261  if(!nAttr) return;
262 
263  std::string pattern = "";
264  for(int i=0;i<nAttr;++i) pattern += "\\s+(\\|?[_[:alnum:]]+\\|?)\\s*=\\s*\"([_[:alnum:]\\s,-\\[\\]\\.\\|]+)\"";
265 
266  std::cmatch cmr;
267  if(!std::regex_match(stream.ptr, stream.endptr, cmr, std::regex(pattern)))
268  {
269  throw(XmlError(stream) << "unexpected error (internal))");
270  }
271  for(unsigned i=1;i<cmr.size();i+=2)
272  {
273  auto attr = cmr[i].str();
274  auto itr = attributes.find(tag + '/' + attr);
275  if(itr == attributes.end())
276  {
277  throw(XmlError(stream.ptr+cmr.position(i), attr.length()) << "invalid attribute \"" << attr << "\"");
278  }
279  if(!cmr.length(i+1))
280  {
281  throw(XmlError(stream.ptr+cmr.position(i), attr.length()) << "empty value for attribute \"" << attr << "\"");
282  }
283  auto& attrVal = itr->second;
284  if(attrVal) throw(XmlError(stream.ptr+cmr.position(i), attr.length()) << "the attribute \"" << attr << "\" has already been specified for that tag");
285  attrVal.set(stream.ptr+cmr.position(i+1), cmr.length(i+1));
286  }
287 }
288 
290 {
291  std::regex rx("<!--.*?-->");
292  std::smatch smr;
293  while(std::regex_search(buffer, smr, rx))
294  {
295  std::size_t pos = smr.position(0), length = smr.length(), endpos = pos + length;
296  for(auto& offset : m_lineOffset)
297  {
298  if(offset > endpos) offset -= length;
299  else if(offset > pos) offset = pos;
300  }
301  buffer = smr.prefix().str() + smr.suffix().str();
302  }
303 }
304 
305 void Database::dropRootTag(std::string& buffer)
306 {
307  const std::vector<std::string> keys = {"<efficiencies>", "</efficiencies>"};
308  for(const auto& key : keys)
309  {
310  std::size_t ipos;
311  while((ipos = buffer.find(key)) != std::string::npos)
312  {
313  buffer.erase(ipos, key.length()-1);
314  buffer[ipos] = ' ';
315  }
316  }
317 }
318 
319 std::vector<std::string> Database::getListOfNames(const StringRef& stream)
320 {
321  std::vector<std::string> words;
322  std::stringstream ss(std::string(stream.ptr, stream.endptr));
323  std::string w;
324  while(std::getline(ss, w, ','))
325  {
326  std::size_t i = w.find_first_not_of(" \t");
327  std::size_t j = w.find_last_not_of(" \t");
328  if(i == std::string::npos)
329  {
330  throw(XmlError(stream) << "this should be a comma-separated list of names");
331  }
332  words.push_back(w.substr(i, j-i+1));
333  }
334  return words;
335 }
336 
337 template<typename ReturnValue>
338 ReturnValue Database::getAttribute(const StringRef& attr, const char* ref, ReturnValue rv)
339 {
340  if(attr.str() == ref) return rv;
341  throw(XmlError(attr) << "unsupported parameter type \"" << attr.str() << "\"");
342 }
343 
344 template<typename ReturnValue, typename... Args>
345 ReturnValue Database::getAttribute(const StringRef& attr, const char* ref, ReturnValue rv, Args... args)
346 {
347  if(attr.str() == ref) return rv;
348  return getAttribute(attr, args...);
349 }
350 
351 template<typename ReturnValue, typename... Args>
352 ReturnValue Database::getAttribute(const StringRef& tag, const AttributesMap& attributes, const std::string& type, const char* ref, ReturnValue rv, Args... args)
353 {
354  std::string attrname = tag.str() + "/" + type;
355  auto& attr = attributes.at(attrname);
356  if(!attr) throw(XmlError(tag) << "unspecified value for attribute \"" << type << "\"");
357  return getAttribute(attr, ref, rv, args...);
358 }
359 
361 {
363  auto level = getAttribute(tag, attributes, "level", "particle", Param::Level::PARTICLE, "event", Param::Level::EVENT);
364 
365  for(auto& name: getListOfNames(contents))
366  {
367  if(std::any_of(m_params.begin(), m_params.end(), [&](const Param& p){ return p.name == name; }))
368  {
369  throw(XmlError(contents) << "parameter \"" << name << "\" was already declared");
370  }
371  m_params.emplace_back(name, type, level);
372  attributes["bin/" + name];
373  attributes["table/" + name];
374  }
375 }
376 
378 {
379  std::bitset<N_EFFICIENCY_TYPES> affects;
380  for(auto& target : getListOfNames(attributes.at("syst/affects")))
381  {
382  auto targetMatches = [&](const char* a, const char* b) -> bool
383  { return target==a || target==b || target==std::string(a)+'-'+b; };
384  int matched = 0;
385  if(targetMatches("electron", "real-efficiency")) { affects.set(ELECTRON_REAL_EFFICIENCY); ++matched; }
386  if(targetMatches("muon", "real-efficiency")) { affects.set(MUON_REAL_EFFICIENCY); ++matched; }
387  if(targetMatches("tau", "real-efficiency")) { affects.set(TAU_REAL_EFFICIENCY); ++matched; }
388  if(targetMatches("electron", "fake-efficiency")) { affects.set(ELECTRON_FAKE_EFFICIENCY); ++matched; }
389  if(targetMatches("muon", "fake-efficiency")) { affects.set(MUON_FAKE_EFFICIENCY); ++matched; }
390  if(targetMatches("tau", "fake-efficiency")) { affects.set(TAU_FAKE_EFFICIENCY); ++matched; }
391  if(targetMatches("electron", "fake-factor")) { affects.set(ELECTRON_FAKE_FACTOR); ++matched; }
392  if(targetMatches("muon", "fake-factor")) { affects.set(MUON_FAKE_FACTOR); ++matched; }
393  if(targetMatches("tau", "fake-factor")) { affects.set(TAU_FAKE_FACTOR); ++matched; }
394  if(!matched) throw(XmlError(tag) << "the value \"" << target << "\" specified for the attribute \"affects\" is not recognized");
395  }
396  if(affects.none()) throw(XmlError(tag) << "missing or empty attribute \"affects\"");
397  for(auto& name: getListOfNames(contents))
398  {
399  if(name == "stat") throw(XmlError(contents) << "systematics can't be named \"stat\"");
400  if(std::any_of(m_systs.begin(), m_systs.end(), [&](const SystDef& s){ return s.name==name && (affects&s.affects).any(); }))
401  {
402  throw(XmlError(contents) << "the systematic \"" << name << "\" was already declared previously; duplicates are only allowed if their \"affects\" attributes do not overlap, which is not the case here");
403  }
404  if(m_systs.size() >= maxIndex()) throw(XmlError(contents) << "exceeded max number of systematic uncertainties");
405  m_systs.emplace_back(name, affects);
406  }
407 }
408 
410 {
411  if(m_stats.size() >= maxIndex())
412  {
413  if(pos) throw(XmlError(pos) << "exceeded max number of statistical uncertainties");
414  else throw(GenericError() << "exceeded max number of statistical uncertainties");
415  }
416  m_stats.emplace_back(1 << type);
417  return statIndexToUID(m_stats.size() - 1);
418 }
419 
421 {
423  if(particle == "muon") type = getAttribute(particle, attributes, "type",
424  "real-efficiency", MUON_REAL_EFFICIENCY, "fake-efficiency", MUON_FAKE_EFFICIENCY, "fake-factor", MUON_FAKE_FACTOR);
425  else if(particle == "electron") type = getAttribute(particle, attributes, "type",
426  "real-efficiency", ELECTRON_REAL_EFFICIENCY, "fake-efficiency", ELECTRON_FAKE_EFFICIENCY, "fake-factor", ELECTRON_FAKE_FACTOR);
427  else if(particle == "tau") type = getAttribute(particle, attributes, "type",
428  "real-efficiency", TAU_REAL_EFFICIENCY, "fake-efficiency", TAU_FAKE_EFFICIENCY, "fake-factor", TAU_FAKE_FACTOR);
429  else throw(XmlError(particle) << "unexpected error: unsupported particle type " << particle.str());
430  auto statMode = attributes.at(particle.str()+"/stat") ? getAttribute(particle, attributes, "stat",
432  auto inputType = getAttribute(particle, attributes, "input", "central-value", InputType::CENTRAL_VALUE, "correction", InputType::CORRECTION);
433 
434  unsigned short globalStatUID = 0;
435 
436  AttributesMap subattributes;
437  StringRef stream = contents, subcontents;
438  while(stream.length())
439  {
440  StringRef tag;
441  resetAttributes(subattributes);
442  readNextTag(stream, tag, subattributes, subcontents);
443  const TH1* hist = nullptr;
444  if(tag=="bin" || tag=="table" || tag=="TH1")
445  {
446  if(tag == "TH1")
447  {
448  if(!source) throw(XmlError(tag) << "histograms can only be imported inside <ROOT>...</ROOT> blocks!");
449  if(!subattributes.at("TH1/X")) throw(XmlError(tag) << "the attribute 'X' should be specified (as well as 'Y' for 2D histograms, 'Z' for 3D histograms)");
450  auto name = subcontents.trim();
451  hist = static_cast<const TH1*>(source->Get(name.c_str()));
452  if(!hist) throw(XmlError(subcontents) << "can't find any histogram named \"" << name << "\" in the file " << source->GetName());
453  auto& norm = subattributes.at("TH1/norm");
454  if(inputType!=InputType::CORRECTION && (norm && norm!="none"))
455  throw(XmlError(norm) << "normalization of input histograms is only accepted for 'input=\"correction\"'");
456  float scale = getNormalizationFactor(hist, type, norm, subcontents);
457  importNominalTH1(hist, type, subattributes.at("TH1/X"), subattributes.at("TH1/Y"), subattributes.at("TH1/Z"), scale, statMode, globalStatUID, subcontents);
458  }
459  else m_tables[type].emplace_back();
460  auto& table = m_tables[type].back();
461  table.inputType = inputType;
462 
463  auto initialNumberOfBins = table.numberOfBins();
464  std::map<StringRef, unsigned> dimBins;
465  for(unsigned uid=0; uid<m_params.size(); ++uid)
466  {
467  auto& binning = subattributes.at(tag + "/" + m_params[uid].name);
468  if(binning) dimBins.emplace(binning, uid);
469  }
470  for(auto& kv : dimBins) addDimension(table, kv.second, kv.first);
471 
472  if(tag != "TH1")
473  {
474  if(tag == "bin" && table.numberOfBins() > 1) throw(XmlError(tag) << "use a <table> instead of a <bin> tag to hold several values");
475  addValues(subcontents, table, type, statMode, globalStatUID);
476  }
477  else if(table.numberOfBins() != initialNumberOfBins) throw(XmlError(tag) << "extra binned dimensions do not make sense");
478  if(tag=="TH1" || tag=="bin")
479  {
480  auto& label = subattributes.at(tag + "/label");
481  if(label)
482  {
483  float normFactor {0};
484  if(tag == "TH1") normFactor = 1.f / getWeightedAverage(hist, stream);
485  else
486  {
487  assert (tag == "bin");
488  normFactor = 1.f / table.m_efficiencies[0].nominal;
489  }
490  if(!std::isnormal(normFactor) || normFactor<=0.) throw(XmlError(label) << "computed normalization factor is 0 / NaN / infinite / negative");
491  if(!m_normFactors.emplace(label.str()+"-"+std::to_string(type), normFactor).second)
492  throw(XmlError(label) << "label \"" << label.str() << "\" has already been used");
493  }
494  }
495  }
496  else throw(XmlError(tag) << "unknown/unexpected XML tag \"" << tag.str() << "\"");
497  }
498 }
499 
500 void Database::assertNoLeftover(std::stringstream& ss, const StringRef& pos)
501 {
502  ss >> std::ws;
503  if(!ss.eof())
504  {
505  std::string line;
506  std::getline(ss, line);
507  throw(XmlError(pos) << "unexpected parsing error (leftover data \"" << line << "\")");
508  }
509 }
510 
512 {
513  if(!contents) return;
514  auto& param = m_params[paramUID];
515  const bool integer = param.integer();
516  const std::string fp = "[+-]?[0-9]*\\.?[0-9]+(?:[Ee][+-]?[0-9]+)?";
517  const std::string pattern = "^\\s*\\[\\s*(?:(?:-inf\\s*,\\s*|-?)inf|(?:-inf\\s*,\\s*)?"
518  + fp + "(?:\\s*,\\s*" + fp + ")*(?:\\s*,\\s*inf)?)\\s*\\]\\s*$";
519  if(!std::regex_match(contents.ptr, contents.endptr, std::regex(pattern)))
520  {
522  if(!integer || !std::regex_match(contents.ptr, contents.endptr, std::regex("\\s*[+-]?[0-9]+\\s*")))
523  {
524  throw(XmlError(contents) << "invalid format for the range of the parameter " << param.name);
525  }
526  }
527 
528  auto& bounds = table.m_bounds;
529  table.m_dimensions.emplace_back();
530  auto& dim = table.m_dimensions.back();
531  dim.paramUID = paramUID;
532  dim.iMinBound = table.m_bounds.size();
533  auto line = contents.str();
534  dim.nBounds = std::count(line.begin(), line.end(), ',') + 1;
535  if(integer && dim.nBounds < 1) throw(XmlError(contents) << "should specify at least one bin boundary for parameter " << param.name);
536  if(!integer && (dim.nBounds < 2)) throw(XmlError(contents) << "should specify at least two bin boundaries for parameter " << param.name);
537  for(auto&c : line) if(c==',' || c=='[' || c==']') c = ' ';
538  std::stringstream ss(line);
539  for(int i=0;i<dim.nBounds;++i)
540  {
542  if(integer) ss >> x.as_int;
543  else ss >> x.as_float;
544  if(ss.fail())
545  {
546  if(i==0 || i==(dim.nBounds-1))
547  {
548  ss.clear();
549  ss.unget();
550  ss.clear();
551  std::string x_s;
552  ss >> x_s;
553  if(x_s=="inf" || x_s=="-inf")
554  {
555  bool defMax = (x_s.front() != '-');
557  else x.as_float = defMax ? std::numeric_limits<float>::max() : std::numeric_limits<float>::lowest();
558  }
559  else throw(XmlError(contents) << "parsing error (invalid 'inf' string)");
560  }
561  if(ss.fail()) throw(XmlError(contents) << "parsing error (can't read int/float boundary)");
562  }
563  if(i)
564  {
565  if(integer ? (bounds.back().as_int > x.as_int) : (bounds.back().as_float > x.as_float))
566  {
567  throw(XmlError(contents) << "bin boundaries must be sorted in increasing order");
568  }
569  }
570  bounds.push_back(x);
571  }
573  if(integer && dim.nBounds==1)
574  {
575  dim.nBounds = 2;
576  bounds.push_back(bounds.back());
577  bounds.back().as_int += 1;
578  }
579 }
580 
581 void Database::addValues(const StringRef& contents, EfficiencyTable& table, EfficiencyType type, StatMode statMode, unsigned short& globalStatUID)
582 {
583  const std::string fpv = "(?:[0-9]+\\.)?[0-9]+(?:[Ee][+-]?[0-9]+)?", fpu = fpv + "\\s*\\%?";
584  const std::string pattern = "^\\s*" + fpv + "(?:\\s*(?:\\+(?:\\s*" + fpu + "\\s*)?-|-(?:\\s*" + fpu + "\\s*)?\\+)\\s*" + fpu + "\\s*\\([_[:alnum:]]+\\))*\\s*";
585  auto rxValidFormat = std::regex(pattern);
586  std::stringstream ssCSV(contents.str()), ss;
587  const char* ptr = contents.ptr;
588 
589  if(statMode==StatMode::GLOBAL && !globalStatUID) globalStatUID = addStat(type, contents);
590 
591  while(ptr && ptr<contents.endptr)
592  {
593  std::cmatch cm;
594  if(!std::regex_search(ptr, contents.endptr, cm, rxValidFormat))
595  {
596  StringRef lineref{ptr, contents.endptr};
597  throw(XmlError(lineref) << "the central value(s) and uncertainties are not in the expected format; first issue found with value " << lineref.str().substr(0, 32) << " [...]");
598  }
599  StringRef valref{ptr, static_cast<std::size_t>(cm.length())};
600  ptr += cm.length();
601  std::string value = valref.str();
602  value.erase(std::remove_if(value.begin(), value.end(), [](char c){ return std::isspace(c); }), value.end());
603  unsigned nErrs = std::count(value.begin(), value.end(), '(');
604  for(auto& c : value) if(c=='(' || c==')') c = ' ';
605  ss.clear();
606  ss.str(value);
607  table.m_efficiencies.emplace_back();
608  auto& eff = table.m_efficiencies.back();
609  ss >> eff.nominal;
610  bool foundStat = false;
611  for(unsigned i=0;i<nErrs;++i)
612  {
614  std::string sysname;
615  ss >> std::ws;
616  auto c1 = ss.get();
617  auto c2 = ss.peek();
618  if(c2=='+' || c2=='-')
619  {
620  ss >> c2 >> uncval.up >> sysname;
621  if(sysname == "%")
622  {
623  uncval.up *= 0.01f * eff.nominal;
624  ss >> sysname;
625  }
626  uncval.down = uncval.up;
627  }
628  else
629  {
630  ss >> uncval.up >> c2;
631  if(c2 == '%')
632  {
633  uncval.up *= 0.01f * eff.nominal;
634  ss >> c2;
635  }
636  ss >> uncval.down >> sysname;
637  if(sysname == "%")
638  {
639  uncval.down *= 0.01f * eff.nominal;
640  ss >> sysname;
641  }
642  }
643  if(ss.bad()) throw(XmlError(valref) << "unexpected parsing error");
644  if(std::signbit(uncval.up) != std::signbit(uncval.down)) throw(XmlError(valref) << "one-sided up/down errors");
645  if(c1 == '-')
646  {
647  uncval.up = -uncval.up;
648  uncval.down = -uncval.down;
649  }
650 
651  uint16_t uid;
652  if(sysname == "stat")
653  {
654  if(foundStat) throw(XmlError(valref) << "there can be only one source of statistical uncertainty per bin");
655  if(statMode==StatMode::UNSPECIFIED || statMode==StatMode::NONE) throw(XmlError(valref) << "when using statistical uncertainties, the \"stat\" attribute must be specified (and not set to \"none\")");
656  foundStat = true;
657  uid = (statMode == StatMode::GLOBAL)? globalStatUID : addStat(type, contents);
658  }
659  else
660  {
661  auto sys = std::find_if(m_systs.begin(), m_systs.end(),
662  [&](const SystDef& sd){ return sd.name==sysname && sd.affects[type]; });
663  if(sys == m_systs.end()) throw(XmlError(valref) << "the systematic \"" << sysname << "\" has either not been defined, or does not affect this type of efficiency");
664  unsigned index = sys - m_systs.begin();
665  uid = systIndexToUID(index);
666  }
667  if(!eff.uncertainties.emplace(uid, uncval).second)
668  {
669  throw(XmlError(valref) << "source of uncertainty \"" << sysname << "\" specified twice");
670  }
671  }
673  }
674  if(table.m_efficiencies.size() != table.numberOfBins())
675  {
676  throw(XmlError(contents) << "the number of tabulated efficiencies (" << table.m_efficiencies.size()
677  << ") is inconsistent with the number of bins (" << table.numberOfBins() << ")");
678  }
679 }
680 
682 {
683  std::string filename = attributes.at("ROOT/source").str();
684  if(!filename.length()) throw(XmlError(rootTag) << "the 'file' attribute must be specified!");
686 
687  TFile* file = TFile::Open(filename.c_str(), "READ");
688  if(!file || !file->IsOpen())
689  {
690  delete file;
691  throw(XmlError(rootTag) << "unable to locate/open the file " << filename);
692  }
693 
694  AttributesMap subattributes;
695  StringRef stream = contents, tag, subcontents;
696  while(stream.length())
697  {
698  resetAttributes(subattributes);
699  readNextTag(stream, tag, subattributes, subcontents);
700  if(tag=="electron" || tag=="muon" || tag=="tau") addTables(tag, subattributes, subcontents, file);
701  else throw(XmlError(stream) << "unknown/unexpected XML tag \"" << tag << "\"");
702  }
703 
704  file->Close();
705  delete file;
706 }
707 
709 {
710  attributes["ROOT/source"];
711  attributes["param/type"];
712  attributes["param/level"];
713  attributes["syst/affects"];
714 
715  const std::vector<std::string> parts = {"electron", "muon", "tau"};
716  for(const auto& p : parts)
717  {
718  attributes[p + "/type"];
719  attributes[p + "/input"];
720  attributes[p + "/stat"];
721  }
722  attributes["TH1/X"];
723  attributes["TH1/Y"];
724  attributes["TH1/Z"];
725  attributes["TH1/label"];
726  attributes["bin/label"];
727  attributes["TH1/norm"];
728  for(auto& p : m_params)
729  {
730  attributes["bin/" + p.name];
731  attributes["table/" + p.name];
732  attributes["TH1/" + p.name];
735  }
736 }
737 
738 /*
739  * Loading from ROOT
740  */
741 
743 {
744  const std::string prefix = "^(FakeFactor|FakeEfficiency|RealEfficiency|FakeRate|FakeRateSF)", suffix = "_([[:w:]][^_]+)(__[[:w:]]+)?$";
745  const std::regex rxTH1(prefix + "_(el|mu|tau|e2y)" + suffix);
746  const std::regex rxTH2(prefix + "2D_(el|mu|tau|e2y)_([[:alnum:]]+)" + suffix);
747  const std::regex rxTH3(prefix + "3D_(el|mu|tau)_([[:alnum:]]+)_([[:alnum:]]+)" + suffix);
748 
750  TFile* file = TFile::Open(filename.c_str(), "READ");
751  if(!file || !file->IsOpen())
752  {
753  throw(GenericError() << "unable to locate/open the file " << filename);
754  }
755 
756  auto keys = file->GetListOfKeys();
757  if(!keys) throw(GenericError() << "unable to list keys in the file " << filename << " (corrupted?)");
758 
759  const StringRef nullStream;
760  unsigned short dummy;
761  for(unsigned step=0;step<2;++step)
762  {
765  for(int i=0;i<keys->GetSize();++i)
766  {
767  TKey* key = static_cast<TKey*>(keys->At(i));
768  std::cmatch mr;
769  std::string keyType = key->GetClassName();
770  unsigned nDims = 0;
771  if(keyType=="TH1F" || keyType=="TH1D") nDims = 1 * std::regex_match(key->GetName(), mr, rxTH1);
772  else if(keyType=="TH2F" || keyType=="TH2D") nDims = 2 * std::regex_match(key->GetName(), mr, rxTH2);
773  else if(keyType=="TH3F" || keyType=="TH3D") nDims = 3 * std::regex_match(key->GetName(), mr, rxTH3);
774  else continue;
775  if(nDims < 1) throw(GenericError() << "don't know what to do with histogram named \"" << key->GetName() << "\" (please check naming conventions)");
776  TH1* hist = static_cast<TH1*>(key->ReadObj());
778  std::string sss = mr[1].str() + "-" + mr[2].str();
779  auto type = getAttribute(StringRef(sss.data(), sss.length()),
780  "FakeFactor-el", ELECTRON_FAKE_FACTOR, "FakeFactor-mu", MUON_FAKE_FACTOR, "FakeFactor-tau", TAU_FAKE_FACTOR,
781  "FakeEfficiency-el", ELECTRON_FAKE_EFFICIENCY, "FakeEfficiency-mu", MUON_FAKE_EFFICIENCY, "FakeEfficiency-tau", TAU_FAKE_EFFICIENCY,
782  "RealEfficiency-el", ELECTRON_REAL_EFFICIENCY, "RealEfficiency-mu", MUON_REAL_EFFICIENCY, "RealEfficiency-tau", TAU_REAL_EFFICIENCY,
783  "FakeRate-e2y", PHOTON_ELE_FAKE_FACTOR, "FakeRateSF-e2y", PHOTON_ELE_FAKE_FACTOR_SF
784  );
785  bool systTH1 = (mr[mr.size()-1].str() != "");
786  if(step==0 && !systTH1)
787  {
788  StringRef paramX = StringRef(mr[3].first, mr[3].second);
789  StringRef paramY = (nDims>1) ? StringRef(mr[4].first, mr[4].second) : StringRef();
790  StringRef paramZ = (nDims>2) ? StringRef(mr[5].first, mr[5].second) : StringRef();
791  importNominalTH1(hist, type, paramX, paramY, paramZ, 1.f, StatMode::PER_BIN, dummy, nullStream);
792  m_tables[type].back().inputType = InputType::CENTRAL_VALUE;
793  }
794  else if(step==1 && systTH1) importSystTH1(hist, type, mr[nDims+3].str().substr(2));
795  else continue;
796  }
797  }
798 
799  file->Close();
800  delete file;
801 }
802 
803 float Database::getWeightedAverage(const TH1* hist, const StringRef& xmlStream)
804 {
805  float avg = 1.f;
806  if(hist->GetNbinsX()!=1 || hist->GetNbinsY()!=1 || hist->GetNbinsZ()!=1)
807  {
809  double sum = 0., denom = 0.;
810  for(int i=1;i<=hist->GetNbinsX();++i)
811  for(int j=1;j<=hist->GetNbinsY();++j)
812  for(int k=1;k<=hist->GetNbinsZ();++k)
813  {
814  double x = hist->GetBinContent(i, j, k);
815  if(x == 0.) continue;
816  double w = hist->GetBinError(i, j, k);
817  if(w == 0.) throw(XmlError(xmlStream) << "bin with error = 0 encountered when trying to normalize histogram " << hist->GetName() << " to weighted bins average");
818  w = 1./(w*w);
819  sum += w * x;
820  denom += w;
821  }
822  avg = sum / denom;
823  }
824  else avg = 1. / hist->GetBinContent(1);
825  if(!std::isnormal(avg) || avg<=0.) throw(XmlError(xmlStream) << "something bad happened when trying to compute the weighted average of histogram \""
826  << hist->GetName() << "\" bins, the result ended up 0 / NaN / infinite / negative");
827  return avg;
828 }
829 
831 {
833  if(!norm) return 1.f;
834  auto normType = norm.str();
835  if(normType == "auto") return 1.f / getWeightedAverage(hist, xmlStream);
836  else if(normType != "none")
837  {
838  auto itr = m_normFactors.find(normType + "-" + std::to_string(type));
839  if(itr == m_normFactors.end()) throw(XmlError(norm) << "unknown normalization tag \"" << normType << "\"");
840  return itr->second;
841  }
842  return 1.f;
843 }
844 
845 void Database::importNominalTH1(const TH1* hist, EfficiencyType type, const StringRef& paramX, const StringRef& paramY, const StringRef& paramZ,
846  float scale, StatMode statMode, unsigned short& globalStatUID, const StringRef& xmlStream)
847 {
848  const bool useDefaults = !xmlStream;
849 
850  if(useDefaults && m_tables[type].size()) throw(GenericError() << "already filled that table, please use an XML to describe how to interpret the more complex ROOT files");
851  m_tables[type].emplace_back();
852  auto& table = m_tables[type].back();
853 
854  const int nDims = paramZ? 3 : paramY? 2 : 1;
855  if(hist->GetDimension() != nDims)
856  {
857  if(xmlStream) throw(XmlError(xmlStream) << "histogram " << hist->GetName() << " doesn't have the expected dimension");
858  else throw(GenericError() << "histogram " << hist->GetName() << " doesn't have the expected dimension");
859  }
860 
862  for(int j=0;j<nDims;++j)
863  {
864  std::string name = ((j==2)? paramZ : (j==1)? paramY : paramX).str();
865  const TAxis* axis = (j==2)? hist->GetZaxis() : (j==1)? hist->GetYaxis() : hist->GetXaxis();
866  if(useDefaults && name == "eta" && axis->GetBinLowEdge(1) >= 0) name = "|eta|";
867  table.m_dimensions.emplace_back();
868  auto& dim = table.m_dimensions.back();
869  auto itr = std::find_if(m_params.begin(), m_params.end(), [&](const Param& p){ return p.name == name; });
870  bool integer;
871  if(itr == m_params.end())
872  {
873  if(useDefaults)
874  {
875  dim.paramUID = m_params.size();
877  integer = false;
878  }
879  else throw(XmlError(j? paramY : paramX) << "parameter \"" << name << "\" has not been defined beforehand");
880  }
881  else
882  {
883  dim.paramUID = itr - m_params.begin();
884  integer = itr->integer();
885  }
886  dim.iMinBound = table.m_bounds.size();
887  dim.nBounds = axis->GetNbins() + 1;
889  table.m_bounds.emplace_back();
890  if(integer) table.m_bounds.back().as_int = std::numeric_limits<int>::min();
891  else table.m_bounds.back().as_float = std::numeric_limits<float>::lowest();
892  for(int k=1;k<dim.nBounds-1;++k)
893  {
894  table.m_bounds.emplace_back();
895  if(integer) table.m_bounds.back().as_int = std::ceil(axis->GetBinUpEdge(k));
896  else table.m_bounds.back().as_float = axis->GetBinUpEdge(k);
897  }
898  table.m_bounds.emplace_back();
899  if(integer) table.m_bounds.back().as_int = std::numeric_limits<int>::max();
900  else table.m_bounds.back().as_float = std::numeric_limits<float>::max();
901  }
902 
904  if(statMode==StatMode::GLOBAL && !globalStatUID) globalStatUID = addStat(type, xmlStream);
905  const unsigned xmax = table.m_dimensions.front().nBounds;
906  const unsigned ymax = table.m_dimensions.size()>1? table.m_dimensions[1].nBounds : 2;
907  const unsigned zmax = table.m_dimensions.size()>2? table.m_dimensions[2].nBounds : 2;
908  for(unsigned x=1;x<xmax;++x)
909  for(unsigned y=1;y<ymax;++y)
910  for(unsigned z=1;z<zmax;++z)
911  {
912  table.m_efficiencies.emplace_back();
913  auto& eff = table.m_efficiencies.back();
914  eff.nominal = scale * hist->GetBinContent(x, y, z);
915  if(statMode != StatMode::NONE)
916  {
917  uint16_t uid = (statMode==StatMode::GLOBAL)? globalStatUID : addStat(type, xmlStream);
918  float err = hist->GetBinError(x, y, z);
920  eff.uncertainties.emplace(uid, uncdata);
921  }
922  }
923 }
924 
925 void Database::importSystTH1(const TH1* hist, EfficiencyType type, const std::string& sysname)
926 {
927  if(!m_tables[type].size()) throw(GenericError() << "there should be another histogram containing central values to accompany the histogram " << hist->GetName());
928  auto& table = m_tables[type].back();
929  const int xmax = table.m_dimensions.front().nBounds;
930  const int ymax = table.m_dimensions.size()>1? table.m_dimensions[1].nBounds : 2;
931  const int zmax = table.m_dimensions.size()>2? table.m_dimensions[2].nBounds : 2;
932  if(xmax!=hist->GetNbinsX()+1 || ymax!=hist->GetNbinsY()+1 || zmax!=hist->GetNbinsZ()+1)
933  {
934  throw(GenericError() << "binning mismatch between the nominal histogram and " << hist->GetName());
935  }
936 
937  uint16_t uid;
938  auto itr = std::find_if(m_systs.begin(), m_systs.end(), [&](const SystDef& sys){ return sys.name==sysname; });
939  if(itr != m_systs.end())
940  {
941  uid = systIndexToUID(itr - m_systs.begin());
942  itr->affects.set(type);
943  }
944  else
945  {
946  uid = systIndexToUID(m_systs.size());
947  m_systs.emplace_back(sysname, (1 << type));
948  }
949 
950  //loop through all bins once, to check whether all bins are zero error,
951  //or have the same central value as the nominal
952 
953  bool syst_central_equal_nom_central = true;
954  bool syst_errors_equal_zero = true;
955  bool syst_errors_equal_nom_errors = true;
956 
957  auto eff = table.m_efficiencies.begin();
958  for(int x=1;x<xmax;++x)
959  for(int y=1;y<ymax;++y)
960  for(int z=1;z<zmax;++z)
961  {
962  if (fabs ((float)eff->nominal - (float)hist->GetBinContent(x, y, z)) > 0.001 ){ syst_central_equal_nom_central = false;}
963  if ( hist->GetBinError(x, y, z) != 0 ) { syst_errors_equal_zero = false;}
964  float stat_up = 0;
965  for(auto& kv : eff->uncertainties)
966  {
967  if(!isStatUID(kv.first)) continue;
968  stat_up = kv.second.up; break;
969  }
970  if ( fabs((float) hist->GetBinError(x, y, z) - (float) stat_up ) > 0.001) { syst_errors_equal_nom_errors = false;}
971  ++eff;
972  }
973 
974  // loop bins a second time and determine proceedure using above heuristics
975  eff = table.m_efficiencies.begin();
976  for(int x=1;x<xmax;++x)
977  for(int y=1;y<ymax;++y)
978  for(int z=1;z<zmax;++z)
979  {
980 
981  float err =0;
982  //want to support several possible notations:
983  // a) central values are not the same as nominal: then we can assume
984  // that the central values of the syst histos are the errors,
985  // (default nomenclature from the documentation)
986  // b) if the central values for nominal and this hist are the same
987  // then probably the errors are to be taken from the error bars!
988  // but need to watch out for ambiguous cases
989  //
990  if (syst_central_equal_nom_central){ //central values are the same in nom and sys
991  if (syst_errors_equal_nom_errors ){ // this case is ambiguous. Is it a 100% uncertainty?
992  throw(GenericError() << "The central values and uncertainties for this systematic are identical to the nominal+stat uncertainties. This is ambiguous: did you mean to assign a 100% uncertainty? If so, please set all (unused) error bars to zero. ");
993  } else if (syst_errors_equal_zero ) { //assume here that it was intended as 100% uncertainty
994  err = hist->GetBinContent(x, y, z);
995  } else {
996  err = hist->GetBinError(x, y, z);
997  }
998  } else { // central values are different in nom and sys
999  err = hist->GetBinContent(x, y, z);
1000  }
1001 
1002 
1003  FakeBkgTools::Uncertainty uncdata{err, err};
1004  if(!eff->uncertainties.emplace(uid, uncdata).second)
1005  {
1006  throw(GenericError() << "unexpected error: tried filling twice the same systematic");
1007  }
1008  ++eff;
1009  }
1010 }
1011 
1013 {
1014  #ifdef FAKEBKGTOOLS_ATLAS_ENVIRONMENT
1015  float energy_scale = (m_useGeV? 0.001f : 1.f);
1016  #else
1017  float energy_scale = 1;
1018  #endif
1019  if(param.level == Param::Level::PARTICLE)
1020  {
1022  {
1023  if(param.name=="pt") val.as_float = energy_scale * p.pt();
1024  else if(param.name=="eta") val.as_float = p.eta();
1025  else if(param.name=="|eta|") val.as_float = fabs(p.eta());
1026  else if(param.name=="phi") val.as_float = p.phi();
1027  else return false;
1028  }
1029  else if(param.type == Param::Type::CUSTOM_FLOAT) {
1031  val.as_float = acc(p);
1032  }
1033  else if(param.type == Param::Type::CUSTOM_INT) {
1035  val.as_int = acc(p);
1036  }
1037  else return false;
1038  }
1039  else if(param.level == Param::Level::EVENT)
1040  {
1041  if(param.type == Param::Type::CUSTOM_FLOAT) {
1043  val.as_float = acc(eventInfo);
1044  }
1045  else if(param.type == Param::Type::CUSTOM_INT) {
1047  val.as_int = acc(eventInfo);
1048  }
1049  else return false;
1050  }
1051  else return false;
1052  return true;
1053 }
1054 
1056 {
1057  switch(p.type())
1058  {
1059  case xAOD::Type::Electron:
1060  if(type==ELECTRON_FAKE_FACTOR) return &pd.fake_factor;
1061  else if(type==ELECTRON_FAKE_EFFICIENCY) return &pd.fake_efficiency;
1062  else if(type==ELECTRON_REAL_EFFICIENCY) return &pd.real_efficiency;
1063  else if(type==PHOTON_ELE_FAKE_FACTOR) return &pd.fake_factor;
1064  break;
1065  case xAOD::Type::Muon:
1066  if(type==MUON_FAKE_FACTOR) return &pd.fake_factor;
1067  else if(type==MUON_FAKE_EFFICIENCY) return &pd.fake_efficiency;
1068  else if(type==MUON_REAL_EFFICIENCY) return &pd.real_efficiency;
1069  break;
1070  case xAOD::Type::Tau:
1071  if(type==TAU_FAKE_FACTOR) return &pd.fake_factor;
1072  else if(type==TAU_FAKE_EFFICIENCY) return &pd.fake_efficiency;
1073  else if(type==TAU_REAL_EFFICIENCY) return &pd.real_efficiency;
1074  break;
1075  case xAOD::Type::Photon:
1076  if(type==PHOTON_ELE_FAKE_FACTOR_SF) return &pd.fake_factor;
1077  break;
1078  default:;
1079  }
1080  return nullptr;
1081 }
1082 
1084 auto Database::selectTypesToFill(Client client) -> std::bitset<N_EFFICIENCY_TYPES>
1085 {
1086  std::bitset<N_EFFICIENCY_TYPES> result;
1088  {
1089  result[ELECTRON_REAL_EFFICIENCY] = true;
1090  result[MUON_REAL_EFFICIENCY] = true;
1091  result[TAU_REAL_EFFICIENCY] = true;
1092  result[ELECTRON_FAKE_EFFICIENCY] = true;
1093  result[MUON_FAKE_EFFICIENCY] = true;
1094  result[TAU_FAKE_EFFICIENCY] = true;
1095  }
1097  {
1098  result[ELECTRON_FAKE_FACTOR] = true;
1099  result[MUON_FAKE_FACTOR] = true;
1100  result[TAU_FAKE_FACTOR] = true;
1101  }
1103  {
1104  result[PHOTON_ELE_FAKE_FACTOR] = true;
1105  result[PHOTON_ELE_FAKE_FACTOR_SF] = true;
1106  }
1107  if(result.none()) throw(GenericError() << "unrecognized client type, implementation incomplete");
1108  return result;
1109 }
1110 
1112 {
1113  auto tables = m_tables.find(wantedType);
1114  if((tables==m_tables.end() || !tables->second.size()) && m_convertWhenMissing)
1115  {
1116  switch(wantedType)
1117  {
1120  case TAU_FAKE_EFFICIENCY: return TAU_FAKE_FACTOR;
1123  case TAU_FAKE_FACTOR: return TAU_FAKE_EFFICIENCY;
1126  default:;
1127  }
1128  }
1129  return wantedType;
1130 }
1131 
1132 unsigned Database::getXmlLineNumber(const char* pos) const
1133 {
1134  if(!pos || !m_xmlBuffer.size() || !m_lineOffset.size()) return 0;
1135  if(pos < m_xmlBuffer.data()) return 0;
1136  unsigned offset = pos - m_xmlBuffer.data();
1137  if(offset >= m_xmlBuffer.size()) return 0;
1138  return std::upper_bound(m_lineOffset.begin(), m_lineOffset.end(), offset) - m_lineOffset.begin();
1139 }
1140 
1142 {
1144  switch(type)
1145  {
1146  case ELECTRON_REAL_EFFICIENCY: return "real efficiency (electrons)";
1147  case ELECTRON_FAKE_EFFICIENCY: return "fake efficiency (electrons)";
1148  case ELECTRON_FAKE_FACTOR: return "fake factor (electrons)";
1149  case MUON_REAL_EFFICIENCY: return "real efficiency (muons)";
1150  case MUON_FAKE_EFFICIENCY: return "fake efficiency (muons)";
1151  case MUON_FAKE_FACTOR: return "fake factor (muons)";
1152  case TAU_REAL_EFFICIENCY: return "real efficiency (taus)";
1153  case TAU_FAKE_EFFICIENCY: return "fake efficiency (taus)";
1154  case TAU_FAKE_FACTOR: return "fake factor (taus)";
1155  case PHOTON_ELE_FAKE_FACTOR: return "fake rate (electrons->photons)";
1156  case PHOTON_ELE_FAKE_FACTOR_SF: return "fake rate SF(electrons->photons)";
1157  default:;
1158  }
1159  return "???";
1160 }
1161 
1162 std::string Database::StringRef::trim() const
1163 {
1164  if(!ptr) return "";
1165  auto beg=ptr, end=endptr-1;
1166  while(std::isspace(*beg) && beg<end) ++beg;
1167  while(std::isspace(*end) && end>beg) --end;
1168  return std::string(beg, end+1);
1169 }
FakeBkgTools::Database::StatMode::GLOBAL
@ GLOBAL
mergePhysValFiles.pattern
pattern
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:26
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
FakeBkgTools::Database::readTagAttributes
void readTagAttributes(StringRef stream, const std::string &tag, AttributesMap &attributes)
Definition: Database.cxx:258
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
FakeBkgTools::Database::importXML
void importXML(std::string filename)
Definition: Database.cxx:186
FakeBkgTools::Database::addValues
void addValues(const StringRef &contents, EfficiencyTable &table, EfficiencyType type, StatMode statMode, unsigned short &globalStatUID)
Definition: Database.cxx:581
FakeBkgTools::Uncertainty
Definition: FakeBkgInternals.h:27
FakeBkgTools::Uncertainty::down
float down
Definition: FakeBkgInternals.h:28
FakeBkgTools::Database::StatMode
StatMode
Definition: Database.h:63
PlotCalibFromCool.norm
norm
Definition: PlotCalibFromCool.py:100
FakeBkgTools::Database::m_storeAllUncertainties
bool m_storeAllUncertainties
Definition: Database.h:245
FakeBkgTools::Client::E2Y_FAKE
@ E2Y_FAKE
checkFileSG.line
line
Definition: checkFileSG.py:75
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
xAOD::Electron
Electron_v1 Electron
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Electron.h:17
AddEmptyComponent.binning
binning
Definition: AddEmptyComponent.py:34
FakeBkgTools::Database::EfficiencyTable
Definition: Database.h:68
yodamerge_tmp.dim
dim
Definition: yodamerge_tmp.py:239
get_generator_info.result
result
Definition: get_generator_info.py:21
FakeBkgTools::Database::resetAttributes
void resetAttributes(AttributesMap &attributes)
Definition: Database.cxx:708
hotSpotInTAG.suffix
string suffix
Definition: hotSpotInTAG.py:186
FakeBkgTools::Database::importSystTH1
void importSystTH1(const TH1 *hist, EfficiencyType type, const std::string &sysname)
Definition: Database.cxx:925
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
FakeBkgTools::Efficiency
a structure to hold an efficiency together with a variable number of uncertainties
Definition: FakeBkgInternals.h:40
FakeBkgTools::Database::getSourceType
EfficiencyType getSourceType(EfficiencyType wantedType) const
Definition: Database.cxx:1111
FakeBkgTools::Database::assertNoLeftover
static void assertNoLeftover(std::stringstream &ss, const StringRef &pos)
Definition: Database.cxx:500
FakeBkgTools::Database::N_EFFICIENCY_TYPES
@ N_EFFICIENCY_TYPES
Definition: Database.h:55
index
Definition: index.py:1
FakeBkgTools::Database::m_useGeV
const bool m_useGeV
Definition: Database.h:241
FakeBkgTools::Client::FAKE_FACTOR
@ FAKE_FACTOR
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
PlotCalibFromCool.label
label
Definition: PlotCalibFromCool.py:78
FakeBkgTools::Database::Param::Type::PREDEFINED_INT
@ PREDEFINED_INT
FakeBkgTools::Database::GenericError
This propagates an error message.
Definition: Database.h:136
plotmaker.hist
hist
Definition: plotmaker.py:148
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
FakeBkgTools::Database::StringRef::endptr
const char * endptr
Definition: Database.h:97
FakeBkgTools::Database::EfficiencyTable::BoundType
Definition: Database.h:75
FakeBkgTools::Database::m_xmlBuffer
std::string m_xmlBuffer
Temporary buffers (only used while importing data)
Definition: Database.h:254
extractSporadic.c1
c1
Definition: extractSporadic.py:134
FakeBkgTools::Database::Param::name
std::string name
Definition: Database.h:154
yodamerge_tmp.axis
list axis
Definition: yodamerge_tmp.py:241
FakeBkgTools::Database::needEventInfo
bool needEventInfo() const
Definition: Database.cxx:56
FakeBkgTools::Database::Param::Type::CUSTOM_FLOAT
@ CUSTOM_FLOAT
FakeBkgTools::Database::m_systs
std::vector< SystDef > m_systs
Definition: Database.h:249
bin
Definition: BinsDiffFromStripMedian.h:43
FakeBkgTools::Client
Client
Definition: FakeBkgInternals.h:141
FakeBkgTools::Database::addStat
unsigned short addStat(EfficiencyType type, const StringRef &pos=StringRef())
Definition: Database.cxx:409
FakeBkgTools::Database::m_stats
std::vector< StatDef > m_stats
Definition: Database.h:250
FakeBkgTools::Database::addParams
void addParams(const StringRef &tag, const StringRef &contents, AttributesMap &attributes)
Definition: Database.cxx:360
athena.value
value
Definition: athena.py:124
FakeBkgTools::Database::fillEfficiencies
bool fillEfficiencies(ParticleData &pd, const xAOD::IParticle &p, const xAOD::EventInfo &eventInfo, std::string &error) const
Definition: Database.cxx:65
FakeBkgTools::Database::TAU_REAL_EFFICIENCY
@ TAU_REAL_EFFICIENCY
Definition: Database.h:50
makeDTCalibBlob_pickPhase.pd
pd
Definition: makeDTCalibBlob_pickPhase.py:342
FakeBkgTools::Database::m_params
std::vector< Param > m_params
Permanent buffers.
Definition: Database.h:248
FakeBkgTools::ParticleData
Definition: FakeBkgInternals.h:85
SG::ConstAccessor< float >
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
FakeBkgTools::Client::MATRIX_METHOD
@ MATRIX_METHOD
Args
Definition: test_lwtnn_fastgraph.cxx:12
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:41
FakeBkgTools::Database::m_tables
std::map< int, std::vector< EfficiencyTable > > m_tables
Definition: Database.h:251
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
x
#define x
CP
Select isolated Photons, Electrons and Muons.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:48
FakeBkgTools::Database::getWeightedAverage
float getWeightedAverage(const TH1 *hist, const StringRef &xmlStream)
Definition: Database.cxx:803
FakeBkgTools::Database::readNextTag
void readNextTag(StringRef &stream, StringRef &tag, AttributesMap &attributes, StringRef &contents)
Definition: Database.cxx:235
AthenaPoolTestWrite.stream
string stream
Definition: AthenaPoolTestWrite.py:12
FakeBkgTools::Database::AttributesMap
std::map< std::string, StringRef > AttributesMap
Definition: Database.h:175
mapkey::sys
@ sys
Definition: TElectronEfficiencyCorrectionTool.cxx:42
FakeBkgTools::Database::importNominalTH1
void importNominalTH1(const TH1 *hist, EfficiencyType type, const StringRef &paramX, const StringRef &paramY, const StringRef &paramZ, float scale, StatMode statMode, unsigned short &globalStatUID, const StringRef &xmlStream)
Methods used to load from ROOT files.
Definition: Database.cxx:845
FakeBkgTools::Database::Param::level
Level level
Definition: Database.h:156
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
FakeBkgTools::Database::StringRef::str
std::string str() const
Definition: Database.h:112
FakeBkgTools::Database::EfficiencyType
EfficiencyType
Definition: Database.h:43
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
FakeBkgTools::Database::selectEfficiency
static FakeBkgTools::Efficiency * selectEfficiency(FakeBkgTools::ParticleData &pd, const xAOD::IParticle &p, EfficiencyType type)
Methods used to fill efficiencies.
Definition: Database.cxx:1055
rerun_display.client
client
Definition: rerun_display.py:31
python.selector.AtlRunQuerySelectorLhcOlc.sd
sd
Definition: AtlRunQuerySelectorLhcOlc.py:612
PrepareReferenceFile.regex
regex
Definition: PrepareReferenceFile.py:43
FakeBkgTools::Database::MUON_FAKE_EFFICIENCY
@ MUON_FAKE_EFFICIENCY
Definition: Database.h:48
ExtractEBRunDetails.xml
xml
Definition: ExtractEBRunDetails.py:239
cm
const double cm
Definition: Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/FCAL_ChannelMap.cxx:25
FakeBkgTools::Database::Param
Definition: Database.h:145
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
FakeBkgTools::Database::Param::Level::PARTICLE
@ PARTICLE
FakeBkgTools::Database::InputType::CORRECTION
@ CORRECTION
FakeBkgTools::Database::StringRef::trim
std::string trim() const
Definition: Database.cxx:1162
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
FakeBkgTools::Database::systIndexToUID
static constexpr unsigned short systIndexToUID(unsigned short index)
Definition: Database.h:220
createCoolChannelIdFile.buffer
buffer
Definition: createCoolChannelIdFile.py:12
jobOptions_CavernBackground.inputType
inputType
Definition: jobOptions_CavernBackground.py:21
FakeBkgTools::Database::m_typesToFill
const std::bitset< N_EFFICIENCY_TYPES > m_typesToFill
Definition: Database.h:242
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
FakeBkgTools::Database::MUON_REAL_EFFICIENCY
@ MUON_REAL_EFFICIENCY
Definition: Database.h:47
xAOD::uint16_t
setWord1 uint16_t
Definition: eFexEMRoI_v1.cxx:93
dqt_zlumi_pandas.err
err
Definition: dqt_zlumi_pandas.py:182
lumiFormat.i
int i
Definition: lumiFormat.py:85
z
#define z
trigmenu_modify_prescale_json.fp
fp
Definition: trigmenu_modify_prescale_json.py:53
FakeBkgTools::Database::StatMode::NONE
@ NONE
FakeBkgTools
Definition: BaseFakeBkgTool.h:23
FakeBkgTools::Database::addDimension
void addDimension(EfficiencyTable &table, unsigned paramUID, const StringRef &contents)
Definition: Database.cxx:511
python.selection.integer
integer
Definition: selection.py:18
Recovery.avg
def avg(a, b)
Definition: Recovery.py:79
FakeBkgTools::Database::m_convertWhenMissing
const bool m_convertWhenMissing
Definition: Database.h:244
FakeBkgTools::Database::Database
Database(Client client, bool useGeV, bool convertWhenMissing)
Definition: Database.cxx:26
FakeBkgTools::Database::m_lineOffset
std::vector< std::size_t > m_lineOffset
Definition: Database.h:255
FakeBkgTools::Database::TAU_FAKE_EFFICIENCY
@ TAU_FAKE_EFFICIENCY
Definition: Database.h:51
FakeBkgTools::Database::reset
void reset()
Definition: Database.cxx:34
FakeBkgTools::Database::readEfficiencyFromTable
int readEfficiencyFromTable(Efficiency &eff, const EfficiencyTable &table, std::map< unsigned, EfficiencyTable::BoundType > &cachedParamVals, const xAOD::IParticle &p, const xAOD::EventInfo &eventInfo, std::string &error) const
Definition: Database.cxx:130
FakeBkgTools::Database::XmlError
This propagates an error message + the reference to the faulty piece of XML when an exception is rais...
Definition: Database.h:124
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
file
TFile * file
Definition: tile_monitor.h:29
PixelAthClusterMonAlgCfg.zmax
zmax
Definition: PixelAthClusterMonAlgCfg.py:169
FakeBkgTools::Database::PHOTON_ELE_FAKE_FACTOR_SF
@ PHOTON_ELE_FAKE_FACTOR_SF
Definition: Database.h:54
FakeBkgTools::Database::PHOTON_ELE_FAKE_FACTOR
@ PHOTON_ELE_FAKE_FACTOR
Definition: Database.h:53
FakeBkgTools::Database::m_normFactors
std::map< std::string, float > m_normFactors
Definition: Database.h:256
AthenaPoolTestRead.acc
acc
Definition: AthenaPoolTestRead.py:16
python.xAODType.dummy
dummy
Definition: xAODType.py:4
hist_file_dump.f
f
Definition: hist_file_dump.py:135
FakeBkgTools::Database::MUON_FAKE_FACTOR
@ MUON_FAKE_FACTOR
Definition: Database.h:49
FakeBkgTools::Database::selectTypesToFill
static std::bitset< N_EFFICIENCY_TYPES > selectTypesToFill(Client client)
This function is only called by the Database constructor.
Definition: Database.cxx:1084
FakeBkgTools::Database::ELECTRON_FAKE_EFFICIENCY
@ ELECTRON_FAKE_EFFICIENCY
Definition: Database.h:45
FakeBkgTools::Database::Param::type
Type type
Definition: Database.h:155
contents
void contents(std::vector< std::string > &keys, TDirectory *td, const std::string &directory, const std::string &pattern, const std::string &path)
Definition: computils.cxx:320
compute_lumi.denom
denom
Definition: compute_lumi.py:76
FakeBkgTools::Database::Param::Level::EVENT
@ EVENT
FakeBkgTools::Database::getTypeAsString
static std::string getTypeAsString(EfficiencyType type)
Definition: Database.cxx:1141
python.update_ci_reference_files.mr
mr
Definition: update_ci_reference_files.py:415
FakeBkgTools::Database::getListOfNames
std::vector< std::string > getListOfNames(const StringRef &stream)
Definition: Database.cxx:319
FakeBkgTools::Database::statIndexToUID
static constexpr unsigned short statIndexToUID(unsigned short index)
Definition: Database.h:221
PathResolver.h
Database.h
FakeBkgTools::Database::SystDef
Definition: Database.h:162
WriteBchToCool.beg
beg
Definition: WriteBchToCool.py:69
FakeBkgTools::Database::StatMode::UNSPECIFIED
@ UNSPECIFIED
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
FakeBkgTools::Database::importDefaultROOT
void importDefaultROOT(std::string filename)
Definition: Database.cxx:742
FakeBkgTools::Database::Param::Type::PREDEFINED_FLOAT
@ PREDEFINED_FLOAT
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
plotBeamSpotVxVal.bin
int bin
Definition: plotBeamSpotVxVal.py:83
FakeBkgTools::Database::retrieveParameterValue
bool retrieveParameterValue(const xAOD::IParticle &p, const xAOD::EventInfo &eventInfo, const Param &param, EfficiencyTable::BoundType &val) const
Definition: Database.cxx:1012
FakeBkgTools::Database::TAU_FAKE_FACTOR
@ TAU_FAKE_FACTOR
Definition: Database.h:52
python.ext.table_printer.table
list table
Definition: table_printer.py:81
python.ElectronD3PDObject.matched
matched
Definition: ElectronD3PDObject.py:138
FakeBkgTools::Database::maxIndex
static constexpr unsigned short maxIndex()
Definition: Database.h:209
dq_make_web_display.rv
def rv
Definition: dq_make_web_display.py:219
FakeBkgTools::Database::getAttribute
static ReturnValue getAttribute(const StringRef &tag, const AttributesMap &attributes, const std::string &type, const char *ref, ReturnValue rv, Args... args)
Helper methods.
Definition: Database.cxx:352
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
xAOD::EventInfo_v1
Class describing the basic event information.
Definition: EventInfo_v1.h:43
xAOD::Photon
Photon_v1 Photon
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Photon.h:17
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
Muon
struct TBPatternUnitContext Muon
FakeBkgTools::Database::getNormalizationFactor
float getNormalizationFactor(const TH1 *hist, EfficiencyType type, const StringRef &norm, const StringRef &xmlStream)
Definition: Database.cxx:830
FakeBkgTools::Uncertainty::up
float up
Definition: FakeBkgInternals.h:28
FakeBkgTools::Database::StringRef
Note: the following structure is used (instead of a simple std::string) so that XML line numbers can ...
Definition: Database.h:96
FakeBkgTools::Database::getXmlLineNumber
unsigned getXmlLineNumber(const char *pos) const
Definition: Database.cxx:1132
python.DataFormatRates.c2
c2
Definition: DataFormatRates.py:123
FakeBkgTools::Database::ELECTRON_FAKE_FACTOR
@ ELECTRON_FAKE_FACTOR
Definition: Database.h:46
a
TList * a
Definition: liststreamerinfos.cxx:10
y
#define y
FakeBkgTools::Client::ALL_METHODS
@ ALL_METHODS
python.CaloScaleNoiseConfig.str
str
Definition: CaloScaleNoiseConfig.py:78
ref
const boost::regex ref(r_ef)
FakeBkgTools::Database::InputType::CENTRAL_VALUE
@ CENTRAL_VALUE
copySelective.target
string target
Definition: copySelective.py:37
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
DeMoScan.first
bool first
Definition: DeMoScan.py:536
xmax
double xmax
Definition: listroot.cxx:61
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
CaloCellTimeCorrFiller.filename
filename
Definition: CaloCellTimeCorrFiller.py:24
FakeBkgTools::Database::StringRef::ptr
const char * ptr
Definition: Database.h:97
FakeBkgTools::Database::Param::Type::CUSTOM_INT
@ CUSTOM_INT
LArCellBinning.step
step
Definition: LArCellBinning.py:158
FakeBkgTools::Database::ready
bool ready() const
Definition: Database.cxx:46
FakeBkgTools::Database::addSysts
void addSysts(const StringRef &tag, const StringRef &contents, const AttributesMap &attributes)
Definition: Database.cxx:377
collListGuids.attributes
attributes
Definition: collListGuids.py:46
xAODType::Tau
@ Tau
The object is a tau (jet)
Definition: ObjectType.h:49
FakeBkgTools::Database::isStatUID
static constexpr bool isStatUID(unsigned short uid)
Definition: Database.h:223
doL1CaloHVCorrections.parts
parts
Definition: doL1CaloHVCorrections.py:334
dqt_zlumi_alleff_HIST.eff
int eff
Definition: dqt_zlumi_alleff_HIST.py:113
copySelective.source
string source
Definition: copySelective.py:32
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:798
merge.status
status
Definition: merge.py:17
FakeBkgTools::Database::dropXmlComments
void dropXmlComments(std::string &buffer)
Methods used to parse XML files.
Definition: Database.cxx:289
CaloCondBlobAlgs_fillNoiseFromASCII.tag
string tag
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:24
FakeBkgTools::Database::addTables
void addTables(const StringRef &particleType, const AttributesMap &attributes, const StringRef &contents, TFile *source=nullptr)
Definition: Database.cxx:420
ConstAccessor.h
Helper class to provide constant type-safe access to aux data.
FakeBkgTools::Database::importCustomROOT
void importCustomROOT(const StringRef &tag, const StringRef &contents, const AttributesMap &attributes)
Definition: Database.cxx:681
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:200
checkFileSG.words
words
Definition: checkFileSG.py:76
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
error
Definition: IImpactPoint3dEstimator.h:70
FakeBkgTools::Database::StatMode::PER_BIN
@ PER_BIN
python.compressB64.c
def c
Definition: compressB64.py:93
length
double length(const pvec &v)
Definition: FPGATrackSimLLPDoubletHoughTransformTool.cxx:26
FakeBkgTools::Database::ELECTRON_REAL_EFFICIENCY
@ ELECTRON_REAL_EFFICIENCY
Definition: Database.h:44
python.CaloScaleNoiseConfig.args
args
Definition: CaloScaleNoiseConfig.py:80
IFakeBkgTool.h
fitman.k
k
Definition: fitman.py:528
ymax
double ymax
Definition: listroot.cxx:64
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
FakeBkgTools::Database::dropRootTag
void dropRootTag(std::string &buffer)
Definition: Database.cxx:305