ATLAS Offline Software
Loading...
Searching...
No Matches
FakeBkgTools::Database Class Reference

#include <Database.h>

Collaboration diagram for FakeBkgTools::Database:

Classes

struct  EfficiencyTable
struct  StringRef
 Note: the following structure is used (instead of a simple std::string) so that XML line numbers can be printed in the error message, which requires keeping track of the position of the string in the original file. More...
struct  XmlError
 This propagates an error message + the reference to the faulty piece of XML when an exception is raised. More...
struct  GenericError
 This propagates an error message. More...
struct  Param
struct  SystDef
struct  StatDef
 could try to keep track of the bin number, for the description More...

Public Types

enum  EfficiencyType {
  ELECTRON_REAL_EFFICIENCY = 0 , ELECTRON_FAKE_EFFICIENCY , ELECTRON_FAKE_FACTOR , MUON_REAL_EFFICIENCY ,
  MUON_FAKE_EFFICIENCY , MUON_FAKE_FACTOR , TAU_REAL_EFFICIENCY , TAU_FAKE_EFFICIENCY ,
  TAU_FAKE_FACTOR , PHOTON_ELE_FAKE_FACTOR , PHOTON_ELE_FAKE_FACTOR_SF , N_EFFICIENCY_TYPES
}
enum class  InputType { CENTRAL_VALUE , CORRECTION }
enum class  StatMode { GLOBAL , PER_BIN , NONE , UNSPECIFIED }

Public Member Functions

 Database (Client client, bool useGeV, bool convertWhenMissing)
void importXML (std::string filename)
void importDefaultROOT (std::string filename)
bool ready () const
void reset ()
bool needEventInfo () const
bool fillEfficiencies (ParticleData &pd, const xAOD::IParticle &p, const xAOD::EventInfo *eventInfo, std::string &error) const
unsigned getXmlLineNumber (const char *pos) const
unsigned numberOfStats () const
unsigned numberOfSysts () const
const SystDeffindSyst (unsigned short uid) const
const StatDeffindStat (unsigned short uid) const

Static Public Member Functions

static constexpr unsigned short indexFromUID (unsigned short uid)
static constexpr unsigned short systIndexToUID (unsigned short index)
static constexpr unsigned short statIndexToUID (unsigned short index)
static constexpr bool isSystUID (unsigned short uid)
static constexpr bool isStatUID (unsigned short uid)

Protected Types

using AttributesMap = std::map<std::string, StringRef>

Protected Member Functions

void dropXmlComments (std::string &buffer)
 Methods used to parse XML files.
void dropRootTag (std::string &buffer)
void readNextTag (StringRef &stream, StringRef &tag, AttributesMap &attributes, StringRef &contents)
void readTagAttributes (StringRef stream, const std::string &tag, AttributesMap &attributes)
void resetAttributes (AttributesMap &attributes)
void importCustomROOT (const StringRef &tag, const StringRef &contents, const AttributesMap &attributes)
void addParams (const StringRef &tag, const StringRef &contents, AttributesMap &attributes)
void addSysts (const StringRef &tag, const StringRef &contents, const AttributesMap &attributes)
unsigned short addStat (EfficiencyType type, const StringRef &pos=StringRef())
void addTables (const StringRef &particleType, const AttributesMap &attributes, const StringRef &contents, TFile *source=nullptr)
void addDimension (EfficiencyTable &table, unsigned paramUID, const StringRef &contents)
void addValues (const StringRef &contents, EfficiencyTable &table, EfficiencyType type, StatMode statMode, unsigned short &globalStatUID)
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.
void importSystTH1 (const TH1 *hist, EfficiencyType type, const std::string &sysname)
float getWeightedAverage (const TH1 *hist, const StringRef &xmlStream)
float getNormalizationFactor (const TH1 *hist, EfficiencyType type, const StringRef &norm, const StringRef &xmlStream)
bool retrieveParameterValue (const xAOD::IParticle &p, const xAOD::EventInfo *eventInfo, const Param &param, EfficiencyTable::BoundType &val) const
EfficiencyType getSourceType (EfficiencyType wantedType) const
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
std::vector< std::string > getListOfNames (const StringRef &stream)

Static Protected Member Functions

static FakeBkgTools::EfficiencyselectEfficiency (FakeBkgTools::ParticleData &pd, const xAOD::IParticle &p, EfficiencyType type)
 Methods used to fill efficiencies.
template<typename ReturnValue, typename... Args>
static ReturnValue getAttribute (const StringRef &tag, const AttributesMap &attributes, const std::string &type, const char *ref, ReturnValue rv, Args... args)
 Helper methods.
static void assertNoLeftover (std::stringstream &ss, const StringRef &pos)
static constexpr unsigned short maxIndex ()
static std::string getTypeAsString (EfficiencyType type)
static std::bitset< N_EFFICIENCY_TYPESselectTypesToFill (Client client)
 This function is only called by the Database constructor.

Protected Attributes

const bool m_useGeV
const std::bitset< N_EFFICIENCY_TYPESm_typesToFill
const bool m_convertWhenMissing
bool m_storeAllUncertainties = true
std::vector< Paramm_params
 Permanent buffers.
std::vector< SystDefm_systs
std::vector< StatDefm_stats
std::map< int, std::vector< EfficiencyTable > > m_tables
std::string m_xmlBuffer
 Temporary buffers (only used while importing data).
std::vector< std::size_t > m_lineOffset
std::map< std::string, float > m_normFactors

Static Private Member Functions

template<typename ReturnValue>
static ReturnValue getAttribute (const StringRef &attr, const char *ref, ReturnValue rv)
 don't call these methods directly, use getAttribute(AttributesMap, string, ...) instead
template<typename ReturnValue, typename... Args>
static ReturnValue getAttribute (const StringRef &attr, const char *ref, ReturnValue rv, Args... args)

Detailed Description

Definition at line 28 of file Database.h.

Member Typedef Documentation

◆ AttributesMap

using FakeBkgTools::Database::AttributesMap = std::map<std::string, StringRef>
protected

Definition at line 175 of file Database.h.

Member Enumeration Documentation

◆ EfficiencyType

Enumerator
ELECTRON_REAL_EFFICIENCY 
ELECTRON_FAKE_EFFICIENCY 
ELECTRON_FAKE_FACTOR 
MUON_REAL_EFFICIENCY 
MUON_FAKE_EFFICIENCY 
MUON_FAKE_FACTOR 
TAU_REAL_EFFICIENCY 
TAU_FAKE_EFFICIENCY 
TAU_FAKE_FACTOR 
PHOTON_ELE_FAKE_FACTOR 
PHOTON_ELE_FAKE_FACTOR_SF 
N_EFFICIENCY_TYPES 

Definition at line 42 of file Database.h.

◆ InputType

Enumerator
CENTRAL_VALUE 
CORRECTION 

Definition at line 58 of file Database.h.

59 {
60 CENTRAL_VALUE, CORRECTION
61 };

◆ StatMode

Enumerator
GLOBAL 
PER_BIN 
NONE 
UNSPECIFIED 

Definition at line 62 of file Database.h.

63 {
64 GLOBAL, PER_BIN, NONE, UNSPECIFIED
65 };

Constructor & Destructor Documentation

◆ Database()

Database::Database ( Client client,
bool useGeV,
bool convertWhenMissing )

Definition at line 26 of file Database.cxx.

26 :
27 m_useGeV(useGeV),
29 m_convertWhenMissing(convertWhenMissing)
30{
31 reset();
32}
const std::bitset< N_EFFICIENCY_TYPES > m_typesToFill
Definition Database.h:242
static std::bitset< N_EFFICIENCY_TYPES > selectTypesToFill(Client client)
This function is only called by the Database constructor.
const bool m_convertWhenMissing
Definition Database.h:244

Member Function Documentation

◆ addDimension()

void Database::addDimension ( EfficiencyTable & table,
unsigned paramUID,
const StringRef & contents )
protected

Also accept a simpler syntax for integers (e.g. nJets = "2")

the stream might have consumed the leading '-' in its failed attempt to read a number, so recover it

Definition at line 512 of file Database.cxx.

513{
514 if(!contents) return;
515 auto& param = m_params[paramUID];
516 const bool integer = param.integer();
517 const std::string fp = "[+-]?[0-9]*\\.?[0-9]+(?:[Ee][+-]?[0-9]+)?";
518 const std::string pattern = "^\\s*\\[\\s*(?:(?:-inf\\s*,\\s*|-?)inf|(?:-inf\\s*,\\s*)?"
519 + fp + "(?:\\s*,\\s*" + fp + ")*(?:\\s*,\\s*inf)?)\\s*\\]\\s*$";
520 if(!std::regex_match(contents.ptr, contents.endptr, std::regex(pattern)))
521 {
523 if(!integer || !std::regex_match(contents.ptr, contents.endptr, std::regex("\\s*[+-]?[0-9]+\\s*")))
524 {
525 throw(XmlError(contents) << "invalid format for the range of the parameter " << param.name);
526 }
527 }
528
529 auto& bounds = table.m_bounds;
530 table.m_dimensions.emplace_back();
531 auto& dim = table.m_dimensions.back();
532 dim.paramUID = paramUID;
533 dim.iMinBound = table.m_bounds.size();
534 auto line = contents.str();
535 dim.nBounds = std::count(line.begin(), line.end(), ',') + 1;
536 if(integer && dim.nBounds < 1) throw(XmlError(contents) << "should specify at least one bin boundary for parameter " << param.name);
537 if(!integer && (dim.nBounds < 2)) throw(XmlError(contents) << "should specify at least two bin boundaries for parameter " << param.name);
538 for(auto&c : line) if(c==',' || c=='[' || c==']') c = ' ';
539 std::stringstream ss(line);
540 for(int i=0;i<dim.nBounds;++i)
541 {
543 if(integer) ss >> x.as_int;
544 else ss >> x.as_float;
545 if(ss.fail())
546 {
547 if(i==0 || i==(dim.nBounds-1))
548 {
549 ss.clear();
550 ss.unget();
551 ss.clear();
552 std::string x_s;
553 ss >> x_s;
554 if(x_s=="inf" || x_s=="-inf")
555 {
556 bool defMax = (x_s.front() != '-');
557 if(integer) x.as_int = defMax ? std::numeric_limits<int>::max() : std::numeric_limits<int>::min();
558 else x.as_float = defMax ? std::numeric_limits<float>::max() : std::numeric_limits<float>::lowest();
559 }
560 else throw(XmlError(contents) << "parsing error (invalid 'inf' string)");
561 }
562 if(ss.fail()) throw(XmlError(contents) << "parsing error (can't read int/float boundary)");
563 }
564 if(i)
565 {
566 if(integer ? (bounds.back().as_int > x.as_int) : (bounds.back().as_float > x.as_float))
567 {
568 throw(XmlError(contents) << "bin boundaries must be sorted in increasing order");
569 }
570 }
571 bounds.push_back(x);
572 }
574 if(integer && dim.nBounds==1)
575 {
576 dim.nBounds = 2;
577 bounds.push_back(bounds.back());
578 bounds.back().as_int += 1;
579 }
580}
static Double_t ss
#define x
#define min(a, b)
Definition cfImp.cxx:40
std::vector< Param > m_params
Permanent buffers.
Definition Database.h:248
static void assertNoLeftover(std::stringstream &ss, const StringRef &pos)
Definition Database.cxx:501
void contents(std::vector< std::string > &keys, TDirectory *td, const std::string &directory, const std::string &pattern, const std::string &path)
setRawEt setRawPhi int
c *Fortran *type rwl_lhe_block sequence integer rad_kinreg real aqcdup integer
Definition pwhg_rwl.h:7
This propagates an error message + the reference to the faulty piece of XML when an exception is rais...
Definition Database.h:124

◆ addParams()

void Database::addParams ( const StringRef & tag,
const StringRef & contents,
AttributesMap & attributes )
protected

Definition at line 361 of file Database.cxx.

362{
363 auto type = getAttribute(tag, attributes, "type", "int", Param::Type::CUSTOM_INT, "float", Param::Type::CUSTOM_FLOAT);
364 auto level = getAttribute(tag, attributes, "level", "particle", Param::Level::PARTICLE, "event", Param::Level::EVENT);
365
366 for(auto& name: getListOfNames(contents))
367 {
368 if(std::any_of(m_params.begin(), m_params.end(), [&](const Param& p){ return p.name == name; }))
369 {
370 throw(XmlError(contents) << "parameter \"" << name << "\" was already declared");
371 }
372 m_params.emplace_back(name, type, level);
373 attributes["bin/" + name];
374 attributes["table/" + name];
375 }
376}
std::vector< std::string > getListOfNames(const StringRef &stream)
Definition Database.cxx:320
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:353

◆ addStat()

unsigned short Database::addStat ( EfficiencyType type,
const StringRef & pos = StringRef() )
protected

Definition at line 410 of file Database.cxx.

411{
412 if(m_stats.size() >= maxIndex())
413 {
414 if(pos) throw(XmlError(pos) << "exceeded max number of statistical uncertainties");
415 else throw(GenericError() << "exceeded max number of statistical uncertainties");
416 }
417 m_stats.emplace_back(1 << type);
418 return statIndexToUID(m_stats.size() - 1);
419}
static constexpr unsigned short statIndexToUID(unsigned short index)
Definition Database.h:221
std::vector< StatDef > m_stats
Definition Database.h:250
static constexpr unsigned short maxIndex()
Definition Database.h:209
This propagates an error message.
Definition Database.h:136

◆ addSysts()

void Database::addSysts ( const StringRef & tag,
const StringRef & contents,
const AttributesMap & attributes )
protected

Definition at line 378 of file Database.cxx.

379{
380 std::bitset<N_EFFICIENCY_TYPES> affects;
381 for(auto& target : getListOfNames(attributes.at("syst/affects")))
382 {
383 auto targetMatches = [&](const char* a, const char* b) -> bool
384 { return target==a || target==b || target==std::string(a)+'-'+b; };
385 int matched = 0;
386 if(targetMatches("electron", "real-efficiency")) { affects.set(ELECTRON_REAL_EFFICIENCY); ++matched; }
387 if(targetMatches("muon", "real-efficiency")) { affects.set(MUON_REAL_EFFICIENCY); ++matched; }
388 if(targetMatches("tau", "real-efficiency")) { affects.set(TAU_REAL_EFFICIENCY); ++matched; }
389 if(targetMatches("electron", "fake-efficiency")) { affects.set(ELECTRON_FAKE_EFFICIENCY); ++matched; }
390 if(targetMatches("muon", "fake-efficiency")) { affects.set(MUON_FAKE_EFFICIENCY); ++matched; }
391 if(targetMatches("tau", "fake-efficiency")) { affects.set(TAU_FAKE_EFFICIENCY); ++matched; }
392 if(targetMatches("electron", "fake-factor")) { affects.set(ELECTRON_FAKE_FACTOR); ++matched; }
393 if(targetMatches("muon", "fake-factor")) { affects.set(MUON_FAKE_FACTOR); ++matched; }
394 if(targetMatches("tau", "fake-factor")) { affects.set(TAU_FAKE_FACTOR); ++matched; }
395 if(!matched) throw(XmlError(tag) << "the value \"" << target << "\" specified for the attribute \"affects\" is not recognized");
396 }
397 if(affects.none()) throw(XmlError(tag) << "missing or empty attribute \"affects\"");
398 for(auto& name: getListOfNames(contents))
399 {
400 if(name == "stat") throw(XmlError(contents) << "systematics can't be named \"stat\"");
401 if(std::any_of(m_systs.begin(), m_systs.end(), [&](const SystDef& s){ return s.name==name && (affects&s.affects).any(); }))
402 {
403 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");
404 }
405 if(m_systs.size() >= maxIndex()) throw(XmlError(contents) << "exceeded max number of systematic uncertainties");
406 m_systs.emplace_back(name, affects);
407 }
408}
static Double_t a
std::vector< SystDef > m_systs
Definition Database.h:249

◆ addTables()

void Database::addTables ( const StringRef & particleType,
const AttributesMap & attributes,
const StringRef & contents,
TFile * source = nullptr )
protected

using the StringRef as map key ensures that dimensions will be listed in the same order as they were written

Definition at line 421 of file Database.cxx.

422{
424 if(particle == "muon") type = getAttribute(particle, attributes, "type",
425 "real-efficiency", MUON_REAL_EFFICIENCY, "fake-efficiency", MUON_FAKE_EFFICIENCY, "fake-factor", MUON_FAKE_FACTOR);
426 else if(particle == "electron") type = getAttribute(particle, attributes, "type",
427 "real-efficiency", ELECTRON_REAL_EFFICIENCY, "fake-efficiency", ELECTRON_FAKE_EFFICIENCY, "fake-factor", ELECTRON_FAKE_FACTOR);
428 else if(particle == "tau") type = getAttribute(particle, attributes, "type",
429 "real-efficiency", TAU_REAL_EFFICIENCY, "fake-efficiency", TAU_FAKE_EFFICIENCY, "fake-factor", TAU_FAKE_FACTOR);
430 else throw(XmlError(particle) << "unexpected error: unsupported particle type " << particle.str());
431 auto statMode = attributes.at(particle.str()+"/stat") ? getAttribute(particle, attributes, "stat",
432 "global", StatMode::GLOBAL, "per-bin", StatMode::PER_BIN, "none", StatMode::NONE) : StatMode::UNSPECIFIED;
433 auto inputType = getAttribute(particle, attributes, "input", "central-value", InputType::CENTRAL_VALUE, "correction", InputType::CORRECTION);
434
435 unsigned short globalStatUID = 0;
436
437 AttributesMap subattributes;
438 StringRef stream = contents, subcontents;
439 while(stream.length())
440 {
442 resetAttributes(subattributes);
443 readNextTag(stream, tag, subattributes, subcontents);
444 const TH1* hist = nullptr;
445 if(tag=="bin" || tag=="table" || tag=="TH1")
446 {
447 if(tag == "TH1")
448 {
449 if(!source) throw(XmlError(tag) << "histograms can only be imported inside <ROOT>...</ROOT> blocks!");
450 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)");
451 auto name = subcontents.trim();
452 hist = static_cast<const TH1*>(source->Get(name.c_str()));
453 if(!hist) throw(XmlError(subcontents) << "can't find any histogram named \"" << name << "\" in the file " << source->GetName());
454 auto& norm = subattributes.at("TH1/norm");
455 if(inputType!=InputType::CORRECTION && (norm && norm!="none"))
456 throw(XmlError(norm) << "normalization of input histograms is only accepted for 'input=\"correction\"'");
457 float scale = getNormalizationFactor(hist, type, norm, subcontents);
458 importNominalTH1(hist, type, subattributes.at("TH1/X"), subattributes.at("TH1/Y"), subattributes.at("TH1/Z"), scale, statMode, globalStatUID, subcontents);
459 }
460 else m_tables[type].emplace_back();
461 auto& table = m_tables[type].back();
462 table.inputType = inputType;
463
464 auto initialNumberOfBins = table.numberOfBins();
465 std::map<StringRef, unsigned> dimBins;
466 for(unsigned uid=0; uid<m_params.size(); ++uid)
467 {
468 auto& binning = subattributes.at(tag + "/" + m_params[uid].name);
469 if(binning) dimBins.emplace(binning, uid);
470 }
471 for(auto& kv : dimBins) addDimension(table, kv.second, kv.first);
472
473 if(tag != "TH1")
474 {
475 if(tag == "bin" && table.numberOfBins() > 1) throw(XmlError(tag) << "use a <table> instead of a <bin> tag to hold several values");
476 addValues(subcontents, table, type, statMode, globalStatUID);
477 }
478 else if(table.numberOfBins() != initialNumberOfBins) throw(XmlError(tag) << "extra binned dimensions do not make sense");
479 if(tag=="TH1" || tag=="bin")
480 {
481 auto& label = subattributes.at(tag + "/label");
482 if(label)
483 {
484 float normFactor {0};
485 if(tag == "TH1") normFactor = 1.f / getWeightedAverage(hist, stream);
486 else
487 {
488 assert (tag == "bin");
489 normFactor = 1.f / table.m_efficiencies[0].nominal;
490 }
491 if(!std::isnormal(normFactor) || normFactor<=0.) throw(XmlError(label) << "computed normalization factor is 0 / NaN / infinite / negative");
492 if(!m_normFactors.emplace(label.str()+"-"+std::to_string(type), normFactor).second)
493 throw(XmlError(label) << "label \"" << label.str() << "\" has already been used");
494 }
495 }
496 }
497 else throw(XmlError(tag) << "unknown/unexpected XML tag \"" << tag.str() << "\"");
498 }
499}
float getNormalizationFactor(const TH1 *hist, EfficiencyType type, const StringRef &norm, const StringRef &xmlStream)
Definition Database.cxx:833
std::map< std::string, StringRef > AttributesMap
Definition Database.h:175
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:848
void addValues(const StringRef &contents, EfficiencyTable &table, EfficiencyType type, StatMode statMode, unsigned short &globalStatUID)
Definition Database.cxx:582
float getWeightedAverage(const TH1 *hist, const StringRef &xmlStream)
Definition Database.cxx:806
void readNextTag(StringRef &stream, StringRef &tag, AttributesMap &attributes, StringRef &contents)
Definition Database.cxx:236
std::map< std::string, float > m_normFactors
Definition Database.h:256
std::map< int, std::vector< EfficiencyTable > > m_tables
Definition Database.h:251
void addDimension(EfficiencyTable &table, unsigned paramUID, const StringRef &contents)
Definition Database.cxx:512
void resetAttributes(AttributesMap &attributes)
Definition Database.cxx:709
std::string label(const std::string &format, int i)
Definition label.h:19
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Type inputType(const std::string &n)
Note: the following structure is used (instead of a simple std::string) so that XML line numbers can ...
Definition Database.h:96

◆ addValues()

void Database::addValues ( const StringRef & contents,
EfficiencyTable & table,
EfficiencyType type,
StatMode statMode,
unsigned short & globalStatUID )
protected

Definition at line 582 of file Database.cxx.

583{
584 const std::string fpv = "(?:[0-9]+\\.)?[0-9]+(?:[Ee][+-]?[0-9]+)?", fpu = fpv + "\\s*\\%?";
585 const std::string pattern = "^\\s*" + fpv + "(?:\\s*(?:\\+(?:\\s*" + fpu + "\\s*)?-|-(?:\\s*" + fpu + "\\s*)?\\+)\\s*" + fpu + "\\s*\\([_[:alnum:]]+\\))*\\s*";
586 auto rxValidFormat = std::regex(pattern);
587 std::stringstream ssCSV(contents.str()), ss;
588 const char* ptr = contents.ptr;
589
590 if(statMode==StatMode::GLOBAL && !globalStatUID) globalStatUID = addStat(type, contents);
591
592 while(ptr && ptr<contents.endptr)
593 {
594 std::cmatch cm;
595 if(!std::regex_search(ptr, contents.endptr, cm, rxValidFormat))
596 {
597 StringRef lineref{ptr, contents.endptr};
598 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) << " [...]");
599 }
600 StringRef valref{ptr, static_cast<std::size_t>(cm.length())};
601 ptr += cm.length();
602 std::string value = valref.str();
603 value.erase(std::remove_if(value.begin(), value.end(), [](char c){ return std::isspace(c); }), value.end());
604 unsigned nErrs = std::count(value.begin(), value.end(), '(');
605 for(auto& c : value) if(c=='(' || c==')') c = ' ';
606 ss.clear();
607 ss.str(value);
608 table.m_efficiencies.emplace_back();
609 auto& eff = table.m_efficiencies.back();
610 ss >> eff.nominal;
611 bool foundStat = false;
612 for(unsigned i=0;i<nErrs;++i)
613 {
614 FakeBkgTools::Uncertainty uncval;
615 std::string sysname;
616 ss >> std::ws;
617 auto c1 = ss.get();
618 auto c2 = ss.peek();
619 if(c2=='+' || c2=='-')
620 {
621 ss >> c2 >> uncval.up >> sysname;
622 if(sysname == "%")
623 {
624 uncval.up *= 0.01f * eff.nominal;
625 ss >> sysname;
626 }
627 uncval.down = uncval.up;
628 }
629 else
630 {
631 ss >> uncval.up >> c2;
632 if(c2 == '%')
633 {
634 uncval.up *= 0.01f * eff.nominal;
635 ss >> c2;
636 }
637 ss >> uncval.down >> sysname;
638 if(sysname == "%")
639 {
640 uncval.down *= 0.01f * eff.nominal;
641 ss >> sysname;
642 }
643 }
644 if(ss.bad()) throw(XmlError(valref) << "unexpected parsing error");
645 if(std::signbit(uncval.up) != std::signbit(uncval.down)) throw(XmlError(valref) << "one-sided up/down errors");
646 if(c1 == '-')
647 {
648 uncval.up = -uncval.up;
649 uncval.down = -uncval.down;
650 }
651
653 if(sysname == "stat")
654 {
655 if(foundStat) throw(XmlError(valref) << "there can be only one source of statistical uncertainty per bin");
656 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\")");
657 foundStat = true;
658 uid = (statMode == StatMode::GLOBAL)? globalStatUID : addStat(type, contents);
659 }
660 else
661 {
662 auto sys = std::find_if(m_systs.begin(), m_systs.end(),
663 [&](const SystDef& sd){ return sd.name==sysname && sd.affects[type]; });
664 if(sys == m_systs.end()) throw(XmlError(valref) << "the systematic \"" << sysname << "\" has either not been defined, or does not affect this type of efficiency");
665 unsigned index = sys - m_systs.begin();
666 uid = systIndexToUID(index);
667 }
668 if(!eff.uncertainties.emplace(uid, uncval).second)
669 {
670 throw(XmlError(valref) << "source of uncertainty \"" << sysname << "\" specified twice");
671 }
672 }
674 }
675 if(table.m_efficiencies.size() != table.numberOfBins())
676 {
677 throw(XmlError(contents) << "the number of tabulated efficiencies (" << table.m_efficiencies.size()
678 << ") is inconsistent with the number of bins (" << table.numberOfBins() << ")");
679 }
680}
static constexpr unsigned short systIndexToUID(unsigned short index)
Definition Database.h:220
unsigned short addStat(EfficiencyType type, const StringRef &pos=StringRef())
Definition Database.cxx:410
str index
Definition DeMoScan.py:362
void * ptr(T *p)
Definition SGImplSvc.cxx:74
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
setWord1 uint16_t

◆ assertNoLeftover()

void Database::assertNoLeftover ( std::stringstream & ss,
const StringRef & pos )
inlinestaticprotected

Definition at line 501 of file Database.cxx.

502{
503 ss >> std::ws;
504 if(!ss.eof())
505 {
506 std::string line;
507 std::getline(ss, line);
508 throw(XmlError(pos) << "unexpected parsing error (leftover data \"" << line << "\")");
509 }
510}

◆ dropRootTag()

void Database::dropRootTag ( std::string & buffer)
protected

Definition at line 306 of file Database.cxx.

307{
308 const std::vector<std::string> keys = {"<efficiencies>", "</efficiencies>"};
309 for(const auto& key : keys)
310 {
311 std::size_t ipos;
312 while((ipos = buffer.find(key)) != std::string::npos)
313 {
314 buffer.erase(ipos, key.length()-1);
315 buffer[ipos] = ' ';
316 }
317 }
318}

◆ dropXmlComments()

void Database::dropXmlComments ( std::string & buffer)
protected

Methods used to parse XML files.

Definition at line 290 of file Database.cxx.

291{
292 std::regex rx("<!--.*?-->");
293 std::smatch smr;
294 while(std::regex_search(buffer, smr, rx))
295 {
296 std::size_t pos = smr.position(0), length = smr.length(), endpos = pos + length;
297 for(auto& offset : m_lineOffset)
298 {
299 if(offset > endpos) offset -= length;
300 else if(offset > pos) offset = pos;
301 }
302 buffer = smr.prefix().str() + smr.suffix().str();
303 }
304}
double length(const pvec &v)
std::vector< std::size_t > m_lineOffset
Definition Database.h:255

◆ fillEfficiencies()

bool Database::fillEfficiencies ( ParticleData & pd,
const xAOD::IParticle & p,
const xAOD::EventInfo * eventInfo,
std::string & error ) const

Loop over all the type of efficiencies (real, fake, fake factor) that were requested to be filled

pointer to the proper member of ParticleData that needs to be filled

The efficiency tables to look for might be for a different type (if a Fake efficiency <--> Fake factor conversion is needed)

Loop over all the tables found for that type of efficiency

an error occurred

this table contained the central values

only a single table should be providing central values (the other tables might provide corrections)

Transform the fake efficiency into fake factor (or reciprocally)

Definition at line 65 of file Database.cxx.

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}
static FakeBkgTools::Efficiency * selectEfficiency(FakeBkgTools::ParticleData &pd, const xAOD::IParticle &p, EfficiencyType type)
Methods used to fill efficiencies.
EfficiencyType getSourceType(EfficiencyType wantedType) const
static std::string getTypeAsString(EfficiencyType type)
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
constexpr int pow(int x)
Definition conifer.h:27
status
Definition merge.py:16

◆ findStat()

const StatDef * FakeBkgTools::Database::findStat ( unsigned short uid) const
inline

Definition at line 232 of file Database.h.

233 {
234 if(!isStatUID(uid)) return nullptr;
235 unsigned index = indexFromUID(uid);
236 return (index<m_stats.size())? &m_stats[index] : nullptr;
237 }
static constexpr unsigned short indexFromUID(unsigned short uid)
Definition Database.h:219
static constexpr bool isStatUID(unsigned short uid)
Definition Database.h:223

◆ findSyst()

const SystDef * FakeBkgTools::Database::findSyst ( unsigned short uid) const
inline

Definition at line 226 of file Database.h.

227 {
228 if(!isSystUID(uid)) return nullptr;
229 unsigned index = indexFromUID(uid);
230 return (index<m_systs.size())? &m_systs[index] : nullptr;
231 }
static constexpr bool isSystUID(unsigned short uid)
Definition Database.h:222

◆ getAttribute() [1/3]

template<typename ReturnValue>
ReturnValue Database::getAttribute ( const StringRef & attr,
const char * ref,
ReturnValue rv )
inlinestaticprivate

don't call these methods directly, use getAttribute(AttributesMap, string, ...) instead

Definition at line 339 of file Database.cxx.

340{
341 if(attr.str() == ref) return rv;
342 throw(XmlError(attr) << "unsupported parameter type \"" << attr.str() << "\"");
343}
const std::regex ref(r_ef)

◆ getAttribute() [2/3]

template<typename ReturnValue, typename... Args>
ReturnValue Database::getAttribute ( const StringRef & attr,
const char * ref,
ReturnValue rv,
Args... args )
inlinestaticprivate

Definition at line 346 of file Database.cxx.

347{
348 if(attr.str() == ref) return rv;
349 return getAttribute(attr, args...);
350}

◆ getAttribute() [3/3]

template<typename ReturnValue, typename... Args>
ReturnValue Database::getAttribute ( const StringRef & tag,
const AttributesMap & attributes,
const std::string & type,
const char * ref,
ReturnValue rv,
Args... args )
inlinestaticprotected

Helper methods.

Definition at line 353 of file Database.cxx.

354{
355 std::string attrname = tag.str() + "/" + type;
356 auto& attr = attributes.at(attrname);
357 if(!attr) throw(XmlError(tag) << "unspecified value for attribute \"" << type << "\"");
358 return getAttribute(attr, ref, rv, args...);
359}

◆ getListOfNames()

std::vector< std::string > Database::getListOfNames ( const StringRef & stream)
protected

Definition at line 320 of file Database.cxx.

321{
322 std::vector<std::string> words;
323 std::stringstream ss(std::string(stream.ptr, stream.endptr));
324 std::string w;
325 while(std::getline(ss, w, ','))
326 {
327 std::size_t i = w.find_first_not_of(" \t");
328 std::size_t j = w.find_last_not_of(" \t");
329 if(i == std::string::npos)
330 {
331 throw(XmlError(stream) << "this should be a comma-separated list of names");
332 }
333 words.push_back(w.substr(i, j-i+1));
334 }
335 return words;
336}
float j(const xAOD::IParticle &, const xAOD::TrackMeasurementValidation &hit, const Eigen::Matrix3d &jab_inv)

◆ getNormalizationFactor()

float Database::getNormalizationFactor ( const TH1 * hist,
EfficiencyType type,
const StringRef & norm,
const StringRef & xmlStream )
protected

Should be called only when processing XMLs

in principle the denominator has been checked not to be 0

Definition at line 833 of file Database.cxx.

834{
836 if(!norm) return 1.f;
837 auto normType = norm.str();
838 if(normType == "auto") return 1.f / getWeightedAverage(hist, xmlStream);
839 else if(normType != "none")
840 {
841 auto itr = m_normFactors.find(normType + "-" + std::to_string(type));
842 if(itr == m_normFactors.end()) throw(XmlError(norm) << "unknown normalization tag \"" << normType << "\"");
843 return itr->second;
844 }
845 return 1.f;
846}

◆ getSourceType()

Database::EfficiencyType Database::getSourceType ( EfficiencyType wantedType) const
protected

Definition at line 1117 of file Database.cxx.

1118{
1119 auto tables = m_tables.find(wantedType);
1120 if((tables==m_tables.end() || !tables->second.size()) && m_convertWhenMissing)
1121 {
1122 switch(wantedType)
1123 {
1132 default:;
1133 }
1134 }
1135 return wantedType;
1136}

◆ getTypeAsString()

std::string Database::getTypeAsString ( EfficiencyType type)
staticprotected

This function is only meant to be used to display meaningful error messages

Definition at line 1147 of file Database.cxx.

1148{
1150 switch(type)
1151 {
1152 case ELECTRON_REAL_EFFICIENCY: return "real efficiency (electrons)";
1153 case ELECTRON_FAKE_EFFICIENCY: return "fake efficiency (electrons)";
1154 case ELECTRON_FAKE_FACTOR: return "fake factor (electrons)";
1155 case MUON_REAL_EFFICIENCY: return "real efficiency (muons)";
1156 case MUON_FAKE_EFFICIENCY: return "fake efficiency (muons)";
1157 case MUON_FAKE_FACTOR: return "fake factor (muons)";
1158 case TAU_REAL_EFFICIENCY: return "real efficiency (taus)";
1159 case TAU_FAKE_EFFICIENCY: return "fake efficiency (taus)";
1160 case TAU_FAKE_FACTOR: return "fake factor (taus)";
1161 case PHOTON_ELE_FAKE_FACTOR: return "fake rate (electrons->photons)";
1162 case PHOTON_ELE_FAKE_FACTOR_SF: return "fake rate SF(electrons->photons)";
1163 default:;
1164 }
1165 return "???";
1166}

◆ getWeightedAverage()

float Database::getWeightedAverage ( const TH1 * hist,
const StringRef & xmlStream )
protected

compute weighted average of all bins

central value of the correction will be 1, but uncertainties may matter, so this is also a valid case

Definition at line 806 of file Database.cxx.

807{
808 float avg = 1.f;
809 if(hist->GetNbinsX()!=1 || hist->GetNbinsY()!=1 || hist->GetNbinsZ()!=1)
810 {
812 double sum = 0., denom = 0.;
813 for(int i=1;i<=hist->GetNbinsX();++i)
814 for(int j=1;j<=hist->GetNbinsY();++j)
815 for(int k=1;k<=hist->GetNbinsZ();++k)
816 {
817 double x = hist->GetBinContent(i, j, k);
818 if(x == 0.) continue;
819 double w = hist->GetBinError(i, j, k);
820 if(w == 0.) throw(XmlError(xmlStream) << "bin with error = 0 encountered when trying to normalize histogram " << hist->GetName() << " to weighted bins average");
821 w = 1./(w*w);
822 sum += w * x;
823 denom += w;
824 }
825 if (denom > 0.) avg = sum / denom;
826 }
827 else avg = 1. / hist->GetBinContent(1);
828 if(!std::isnormal(avg) || avg<=0.) throw(XmlError(xmlStream) << "something bad happened when trying to compute the weighted average of histogram \""
829 << hist->GetName() << "\" bins, the result ended up 0 / NaN / infinite / negative");
830 return avg;
831}
avg(a, b)
Definition Recovery.py:79

◆ getXmlLineNumber()

unsigned Database::getXmlLineNumber ( const char * pos) const

Definition at line 1138 of file Database.cxx.

1139{
1140 if(!pos || !m_xmlBuffer.size() || !m_lineOffset.size()) return 0;
1141 if(pos < m_xmlBuffer.data()) return 0;
1142 unsigned offset = pos - m_xmlBuffer.data();
1143 if(offset >= m_xmlBuffer.size()) return 0;
1144 return std::upper_bound(m_lineOffset.begin(), m_lineOffset.end(), offset) - m_lineOffset.begin();
1145}
std::string m_xmlBuffer
Temporary buffers (only used while importing data).
Definition Database.h:254

◆ importCustomROOT()

void Database::importCustomROOT ( const StringRef & tag,
const StringRef & contents,
const AttributesMap & attributes )
protected

Definition at line 682 of file Database.cxx.

683{
684 std::string filename = attributes.at("ROOT/source").str();
685 if(!filename.length()) throw(XmlError(rootTag) << "the 'file' attribute must be specified!");
687
688 TFile* file = TFile::Open(filename.c_str(), "READ");
689 if(!file || !file->IsOpen())
690 {
691 delete file;
692 throw(XmlError(rootTag) << "unable to locate/open the file " << filename);
693 }
694
695 AttributesMap subattributes;
696 StringRef stream = contents, tag, subcontents;
697 while(stream.length())
698 {
699 resetAttributes(subattributes);
700 readNextTag(stream, tag, subattributes, subcontents);
701 if(tag=="electron" || tag=="muon" || tag=="tau") addTables(tag, subattributes, subcontents, file);
702 else throw(XmlError(stream) << "unknown/unexpected XML tag \"" << tag << "\"");
703 }
704
705 file->Close();
706 delete file;
707}
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
void addTables(const StringRef &particleType, const AttributesMap &attributes, const StringRef &contents, TFile *source=nullptr)
Definition Database.cxx:421
TFile * file

◆ importDefaultROOT()

void Database::importDefaultROOT ( std::string filename)

step 0 = central value + stats step 1 = systs

Efficiency type

Definition at line 743 of file Database.cxx.

744{
745 const std::string prefix = "^(FakeFactor|FakeEfficiency|RealEfficiency|FakeRate|FakeRateSF)", suffix = "_([[:w:]][^_]+)(__[[:w:]]+)?$";
746 const std::regex rxTH1(prefix + "_(el|mu|tau|e2y)" + suffix);
747 const std::regex rxTH2(prefix + "2D_(el|mu|tau|e2y)_([[:alnum:]]+)" + suffix);
748 const std::regex rxTH3(prefix + "3D_(el|mu|tau)_([[:alnum:]]+)_([[:alnum:]]+)" + suffix);
749
750 if (filename[0] != '/')
752
753 TFile* file = TFile::Open(filename.c_str(), "READ");
754 if(!file || !file->IsOpen())
755 {
756 throw(GenericError() << "unable to locate/open the file " << filename);
757 }
758
759 auto keys = file->GetListOfKeys();
760 if(!keys) throw(GenericError() << "unable to list keys in the file " << filename << " (corrupted?)");
761
762 const StringRef nullStream;
763 unsigned short dummy;
764 for(unsigned step=0;step<2;++step)
765 {
768 for(int i=0;i<keys->GetSize();++i)
769 {
770 TKey* key = static_cast<TKey*>(keys->At(i));
771 std::cmatch mr;
772 std::string keyType = key->GetClassName();
773 unsigned nDims = 0;
774 if(keyType=="TH1F" || keyType=="TH1D") nDims = 1 * std::regex_match(key->GetName(), mr, rxTH1);
775 else if(keyType=="TH2F" || keyType=="TH2D") nDims = 2 * std::regex_match(key->GetName(), mr, rxTH2);
776 else if(keyType=="TH3F" || keyType=="TH3D") nDims = 3 * std::regex_match(key->GetName(), mr, rxTH3);
777 else continue;
778 if(nDims < 1) throw(GenericError() << "don't know what to do with histogram named \"" << key->GetName() << "\" (please check naming conventions)");
779 TH1* hist = static_cast<TH1*>(key->ReadObj());
781 std::string sss = mr[1].str() + "-" + mr[2].str();
782 auto type = getAttribute(StringRef(sss.data(), sss.length()),
783 "FakeFactor-el", ELECTRON_FAKE_FACTOR, "FakeFactor-mu", MUON_FAKE_FACTOR, "FakeFactor-tau", TAU_FAKE_FACTOR,
784 "FakeEfficiency-el", ELECTRON_FAKE_EFFICIENCY, "FakeEfficiency-mu", MUON_FAKE_EFFICIENCY, "FakeEfficiency-tau", TAU_FAKE_EFFICIENCY,
785 "RealEfficiency-el", ELECTRON_REAL_EFFICIENCY, "RealEfficiency-mu", MUON_REAL_EFFICIENCY, "RealEfficiency-tau", TAU_REAL_EFFICIENCY,
786 "FakeRate-e2y", PHOTON_ELE_FAKE_FACTOR, "FakeRateSF-e2y", PHOTON_ELE_FAKE_FACTOR_SF
787 );
788 bool systTH1 = (mr[mr.size()-1].str() != "");
789 if(step==0 && !systTH1)
790 {
791 StringRef paramX = StringRef(mr[3].first, mr[3].second);
792 StringRef paramY = (nDims>1) ? StringRef(mr[4].first, mr[4].second) : StringRef();
793 StringRef paramZ = (nDims>2) ? StringRef(mr[5].first, mr[5].second) : StringRef();
794 importNominalTH1(hist, type, paramX, paramY, paramZ, 1.f, StatMode::PER_BIN, dummy, nullStream);
795 m_tables[type].back().inputType = InputType::CENTRAL_VALUE;
796 }
797 else if(step==1 && systTH1) importSystTH1(hist, type, mr[nDims+3].str().substr(2));
798 else continue;
799 }
800 }
801
802 file->Close();
803 delete file;
804}
void importSystTH1(const TH1 *hist, EfficiencyType type, const std::string &sysname)
Definition Database.cxx:928

◆ importNominalTH1()

void Database::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 )
protected

Methods used to load from ROOT files.

Parameters and ranges

Copy, and include under/overflow into first/last bin:

Efficiencies + stat uncertainties

Definition at line 848 of file Database.cxx.

850{
851 const bool useDefaults = !xmlStream;
852
853 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");
854 m_tables[type].emplace_back();
855 auto& table = m_tables[type].back();
856
857 const int nDims = paramZ? 3 : paramY? 2 : 1;
858 if(hist->GetDimension() != nDims)
859 {
860 if(xmlStream) throw(XmlError(xmlStream) << "histogram " << hist->GetName() << " doesn't have the expected dimension");
861 else throw(GenericError() << "histogram " << hist->GetName() << " doesn't have the expected dimension");
862 }
863
865 for(int j=0;j<nDims;++j)
866 {
867 std::string name = ((j==2)? paramZ : (j==1)? paramY : paramX).str();
868 const TAxis* axis = (j==2)? hist->GetZaxis() : (j==1)? hist->GetYaxis() : hist->GetXaxis();
869 if(useDefaults && name == "eta" && axis->GetBinLowEdge(1) >= 0) name = "|eta|";
870 table.m_dimensions.emplace_back();
871 auto& dim = table.m_dimensions.back();
872 auto itr = std::find_if(m_params.begin(), m_params.end(), [&](const Param& p){ return p.name == name; });
873 bool integer;
874 if(itr == m_params.end())
875 {
876 if(useDefaults)
877 {
878 dim.paramUID = m_params.size();
879 m_params.emplace_back(name, Param::Type::CUSTOM_FLOAT, Param::Level::PARTICLE);
880 integer = false;
881 }
882 else throw(XmlError(j? paramY : paramX) << "parameter \"" << name << "\" has not been defined beforehand");
883 }
884 else
885 {
886 dim.paramUID = itr - m_params.begin();
887 integer = itr->integer();
888 }
889 dim.iMinBound = table.m_bounds.size();
890 dim.nBounds = axis->GetNbins() + 1;
892 table.m_bounds.emplace_back();
893 if(integer) table.m_bounds.back().as_int = std::numeric_limits<int>::min();
894 else table.m_bounds.back().as_float = std::numeric_limits<float>::lowest();
895 for(int k=1;k<dim.nBounds-1;++k)
896 {
897 table.m_bounds.emplace_back();
898 if(integer) table.m_bounds.back().as_int = std::ceil(axis->GetBinUpEdge(k));
899 else table.m_bounds.back().as_float = axis->GetBinUpEdge(k);
900 }
901 table.m_bounds.emplace_back();
902 if(integer) table.m_bounds.back().as_int = std::numeric_limits<int>::max();
903 else table.m_bounds.back().as_float = std::numeric_limits<float>::max();
904 }
905
907 if(statMode==StatMode::GLOBAL && !globalStatUID) globalStatUID = addStat(type, xmlStream);
908 const unsigned xmax = table.m_dimensions.front().nBounds;
909 const unsigned ymax = table.m_dimensions.size()>1? table.m_dimensions[1].nBounds : 2;
910 const unsigned zmax = table.m_dimensions.size()>2? table.m_dimensions[2].nBounds : 2;
911 for(unsigned x=1;x<xmax;++x)
912 for(unsigned y=1;y<ymax;++y)
913 for(unsigned z=1;z<zmax;++z)
914 {
915 table.m_efficiencies.emplace_back();
916 auto& eff = table.m_efficiencies.back();
917 eff.nominal = scale * hist->GetBinContent(x, y, z);
918 if(statMode != StatMode::NONE)
919 {
920 uint16_t uid = (statMode==StatMode::GLOBAL)? globalStatUID : addStat(type, xmlStream);
921 float err = hist->GetBinError(x, y, z);
922 FakeBkgTools::Uncertainty uncdata{scale*err, scale*err};
923 eff.uncertainties.emplace(uid, uncdata);
924 }
925 }
926}
size_t size() const
Number of registered mappings.
#define y
#define z
double xmax
Definition listroot.cxx:61
double ymax
Definition listroot.cxx:64

◆ importSystTH1()

void Database::importSystTH1 ( const TH1 * hist,
EfficiencyType type,
const std::string & sysname )
protected

Definition at line 928 of file Database.cxx.

929{
930 if(!m_tables[type].size()) throw(GenericError() << "there should be another histogram containing central values to accompany the histogram " << hist->GetName());
931 auto& table = m_tables[type].back();
932 const int xmax = table.m_dimensions.front().nBounds;
933 const int ymax = table.m_dimensions.size()>1? table.m_dimensions[1].nBounds : 2;
934 const int zmax = table.m_dimensions.size()>2? table.m_dimensions[2].nBounds : 2;
935 if(xmax!=hist->GetNbinsX()+1 || ymax!=hist->GetNbinsY()+1 || zmax!=hist->GetNbinsZ()+1)
936 {
937 throw(GenericError() << "binning mismatch between the nominal histogram and " << hist->GetName());
938 }
939
941 auto itr = std::find_if(m_systs.begin(), m_systs.end(), [&](const SystDef& sys){ return sys.name==sysname; });
942 if(itr != m_systs.end())
943 {
944 uid = systIndexToUID(itr - m_systs.begin());
945 itr->affects.set(type);
946 }
947 else
948 {
949 uid = systIndexToUID(m_systs.size());
950 m_systs.emplace_back(sysname, (1 << type));
951 }
952
953 //loop through all bins once, to check whether all bins are zero error,
954 //or have the same central value as the nominal
955
956 bool syst_central_equal_nom_central = true;
957 bool syst_errors_equal_zero = true;
958 bool syst_errors_equal_nom_errors = true;
959
960 auto eff = table.m_efficiencies.begin();
961 for(int x=1;x<xmax;++x)
962 for(int y=1;y<ymax;++y)
963 for(int z=1;z<zmax;++z)
964 {
965 if (fabs ((float)eff->nominal - (float)hist->GetBinContent(x, y, z)) > 0.001 ){ syst_central_equal_nom_central = false;}
966 if ( hist->GetBinError(x, y, z) != 0 ) { syst_errors_equal_zero = false;}
967 float stat_up = 0;
968 for(auto& kv : eff->uncertainties)
969 {
970 if(!isStatUID(kv.first)) continue;
971 stat_up = kv.second.up; break;
972 }
973 if ( fabs((float) hist->GetBinError(x, y, z) - (float) stat_up ) > 0.001) { syst_errors_equal_nom_errors = false;}
974 ++eff;
975 }
976
977 // loop bins a second time and determine proceedure using above heuristics
978 eff = table.m_efficiencies.begin();
979 for(int x=1;x<xmax;++x)
980 for(int y=1;y<ymax;++y)
981 for(int z=1;z<zmax;++z)
982 {
983
984 float err =0;
985 //want to support several possible notations:
986 // a) central values are not the same as nominal: then we can assume
987 // that the central values of the syst histos are the errors,
988 // (default nomenclature from the documentation)
989 // b) if the central values for nominal and this hist are the same
990 // then probably the errors are to be taken from the error bars!
991 // but need to watch out for ambiguous cases
992 //
993 if (syst_central_equal_nom_central){ //central values are the same in nom and sys
994 if (syst_errors_equal_nom_errors ){ // this case is ambiguous. Is it a 100% uncertainty?
995 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. ");
996 } else if (syst_errors_equal_zero ) { //assume here that it was intended as 100% uncertainty
997 err = hist->GetBinContent(x, y, z);
998 } else {
999 err = hist->GetBinError(x, y, z);
1000 }
1001 } else { // central values are different in nom and sys
1002 err = hist->GetBinContent(x, y, z);
1003 }
1004
1005
1006 FakeBkgTools::Uncertainty uncdata{err, err};
1007 if(!eff->uncertainties.emplace(uid, uncdata).second)
1008 {
1009 throw(GenericError() << "unexpected error: tried filling twice the same systematic");
1010 }
1011 ++eff;
1012 }
1013}

◆ importXML()

void Database::importXML ( std::string filename)

not guaranteed that the above works, so truncating the buffer to a reasonable size if seemingly too large

Definition at line 186 of file Database.cxx.

187{
188 if (filename[0] != '/')
190
191 std::ifstream xml;
192 xml.open(filename, std::ios_base::binary);
193 auto begpos = xml.tellg();
194 xml.seekg(0, std::ios_base::end);
195 std::size_t bufferSize = 1.05 * static_cast<std::size_t>(xml.tellg() - begpos);
197 if(bufferSize > 0x100000) bufferSize = 0x100000;
198 xml.close();
199
200 xml.open(filename, std::ios_base::in);
201 if(!xml.is_open()) throw(GenericError() << "unable to open file " << filename);
202
203 std::string line;
204 m_xmlBuffer.reserve(bufferSize);
205 m_lineOffset.clear();
206 m_lineOffset.push_back(0);
207 while(std::getline(xml, line))
208 {
209 while(line.length() && (line.back()=='\n' || line.back()=='\r')) line.pop_back();
210 m_xmlBuffer += line + ' ';
211 m_lineOffset.push_back(m_xmlBuffer.length());
212 }
213 xml.close();
214
217
219 resetAttributes(attributes);
221 while(stream.length())
222 {
223 readNextTag(stream, tag, attributes, contents);
224 if(tag=="electron" || tag=="muon" || tag=="tau") addTables(tag, attributes, contents);
225 else if(tag=="param") addParams(tag, contents, attributes);
226 else if(tag=="syst") addSysts(tag, contents, attributes);
227 else if(tag=="ROOT") importCustomROOT(tag, contents, attributes);
228 else throw(XmlError(stream) << "unknown/unexpected XML tag \"" << tag.str() << "\"");
229 }
230 m_lineOffset.clear();
231 m_lineOffset.shrink_to_fit();
232 m_xmlBuffer.clear();
233 m_xmlBuffer.shrink_to_fit();
234}
void addSysts(const StringRef &tag, const StringRef &contents, const AttributesMap &attributes)
Definition Database.cxx:378
void dropXmlComments(std::string &buffer)
Methods used to parse XML files.
Definition Database.cxx:290
void addParams(const StringRef &tag, const StringRef &contents, AttributesMap &attributes)
Definition Database.cxx:361
void dropRootTag(std::string &buffer)
Definition Database.cxx:306
void importCustomROOT(const StringRef &tag, const StringRef &contents, const AttributesMap &attributes)
Definition Database.cxx:682

◆ indexFromUID()

constexpr unsigned short FakeBkgTools::Database::indexFromUID ( unsigned short uid)
inlinestaticconstexpr

Definition at line 219 of file Database.h.

219{ return uid&0x3FFF; }

◆ isStatUID()

constexpr bool FakeBkgTools::Database::isStatUID ( unsigned short uid)
inlinestaticconstexpr

Definition at line 223 of file Database.h.

223{ return ((uid&0xC000) == 0x8000); }

◆ isSystUID()

constexpr bool FakeBkgTools::Database::isSystUID ( unsigned short uid)
inlinestaticconstexpr

Definition at line 222 of file Database.h.

222{ return ((uid&0xC000) == 0x4000); }

◆ maxIndex()

constexpr unsigned short FakeBkgTools::Database::maxIndex ( )
inlinestaticconstexprprotected

Definition at line 209 of file Database.h.

209{ return 0x4000; }

◆ needEventInfo()

bool Database::needEventInfo ( ) const

will no longer work if some event-level parameteres are predefined

Definition at line 56 of file Database.cxx.

57{
58 for(auto& param : m_params)
59 {
60 if(param.level == Param::Level::EVENT) return true;
61 }
62 return false;
63}

◆ numberOfStats()

unsigned FakeBkgTools::Database::numberOfStats ( ) const
inline

Definition at line 224 of file Database.h.

224{ return m_stats.size(); }

◆ numberOfSysts()

unsigned FakeBkgTools::Database::numberOfSysts ( ) const
inline

Definition at line 225 of file Database.h.

225{ return m_systs.size(); }

◆ readEfficiencyFromTable()

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
protected

Check if the particle falls in one bin of this table

if not, return

Yes! So read the central value / correction / uncertainties

=> tool will return weight + all uncertainties at once

Definition at line 130 of file Database.cxx.

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}
bool retrieveParameterValue(const xAOD::IParticle &p, const xAOD::EventInfo *eventInfo, const Param &param, EfficiencyTable::BoundType &val) const
bool first
Definition DeMoScan.py:534

◆ readNextTag()

void Database::readNextTag ( StringRef & stream,
StringRef & tag,
AttributesMap & attributes,
StringRef & contents )
protected

Note: when modifying the pattern, make sure to also change readTagAttributes() if required!

Perhaps here do some looser pattern-matching to figure out where the format was not good: missing quotation marks? missing attribute value? no closing tag?

Definition at line 236 of file Database.cxx.

237{
238 tag.clear();
239 contents.clear();
240 for(auto& kv : attributes) kv.second.clear();
242 std::string pattern = "^\\s*(<([[:alnum:]]+)((?:\\s+\\|?[_[:alnum:]]+\\|?\\s*=\\s*\"[_[:alnum:]\\s,-\\[\\]\\.\\|]+\")*)\\s*>)(.*?)</\\2>\\s*";
243 std::cmatch cmr;
244 if(!std::regex_search(stream.ptr, stream.endptr, cmr, std::regex(pattern)))
245 {
247 throw(XmlError(stream) << "unable to find next tag");
248 }
249 tag.set(stream.ptr+cmr.position(2), cmr.length(2));
250
251 readTagAttributes(StringRef(stream.ptr+cmr.position(3), cmr.length(3)), tag.str(), attributes);
252
253 auto cpos = cmr.size()-1;
254 contents.set(stream.ptr+cmr.position(cpos), cmr.length(cpos));
255
256 stream.ptr += cmr.length();
257}
void readTagAttributes(StringRef stream, const std::string &tag, AttributesMap &attributes)
Definition Database.cxx:259

◆ readTagAttributes()

void Database::readTagAttributes ( StringRef stream,
const std::string & tag,
AttributesMap & attributes )
protected

Definition at line 259 of file Database.cxx.

260{
261 auto nAttr = std::count(stream.ptr, stream.endptr, '=');
262 if(!nAttr) return;
263
264 std::string pattern = "";
265 for(int i=0;i<nAttr;++i) pattern += "\\s+(\\|?[_[:alnum:]]+\\|?)\\s*=\\s*\"([_[:alnum:]\\s,-\\[\\]\\.\\|]+)\"";
266
267 std::cmatch cmr;
268 if(!std::regex_match(stream.ptr, stream.endptr, cmr, std::regex(pattern)))
269 {
270 throw(XmlError(stream) << "unexpected error (internal))");
271 }
272 for(unsigned i=1;i<cmr.size();i+=2)
273 {
274 auto attr = cmr[i].str();
275 auto itr = attributes.find(tag + '/' + attr);
276 if(itr == attributes.end())
277 {
278 throw(XmlError(stream.ptr+cmr.position(i), attr.length()) << "invalid attribute \"" << attr << "\"");
279 }
280 if(!cmr.length(i+1))
281 {
282 throw(XmlError(stream.ptr+cmr.position(i), attr.length()) << "empty value for attribute \"" << attr << "\"");
283 }
284 auto& attrVal = itr->second;
285 if(attrVal) throw(XmlError(stream.ptr+cmr.position(i), attr.length()) << "the attribute \"" << attr << "\" has already been specified for that tag");
286 attrVal.set(stream.ptr+cmr.position(i+1), cmr.length(i+1));
287 }
288}

◆ ready()

bool Database::ready ( ) const

Could do some more careful check here; for the moment just check that there's at least one table

Definition at line 46 of file Database.cxx.

47{
49 for(auto& kv : m_tables)
50 {
51 if(kv.second.size()) return true;
52 }
53 return false;
54}

◆ reset()

void Database::reset ( )

Definition at line 34 of file Database.cxx.

35{
36 m_tables.clear();
37 m_systs.clear();
38 m_stats.clear();
39 m_params.clear();
40 m_params.emplace_back("eta", Param::Type::PREDEFINED_FLOAT, Param::Level::PARTICLE);
41 m_params.emplace_back("|eta|", Param::Type::PREDEFINED_FLOAT, Param::Level::PARTICLE);
42 m_params.emplace_back("pt", Param::Type::PREDEFINED_FLOAT, Param::Level::PARTICLE);
43 m_params.emplace_back("phi", Param::Type::PREDEFINED_FLOAT, Param::Level::PARTICLE);
44}

◆ resetAttributes()

void Database::resetAttributes ( AttributesMap & attributes)
protected

for now only a TH1 attribute

NB. the list of attributes allowed for bin or table tags can be further extended by new param tags. This is done inside addParams().

Definition at line 709 of file Database.cxx.

710{
711 attributes["ROOT/source"];
712 attributes["param/type"];
713 attributes["param/level"];
714 attributes["syst/affects"];
715
716 const std::vector<std::string> parts = {"electron", "muon", "tau"};
717 for(const auto& p : parts)
718 {
719 attributes[p + "/type"];
720 attributes[p + "/input"];
721 attributes[p + "/stat"];
722 }
723 attributes["TH1/X"];
724 attributes["TH1/Y"];
725 attributes["TH1/Z"];
726 attributes["TH1/label"];
727 attributes["bin/label"];
728 attributes["TH1/norm"];
729 for(auto& p : m_params)
730 {
731 attributes["bin/" + p.name];
732 attributes["table/" + p.name];
733 attributes["TH1/" + p.name];
736 }
737}

◆ retrieveParameterValue()

bool Database::retrieveParameterValue ( const xAOD::IParticle & p,
const xAOD::EventInfo * eventInfo,
const Param & param,
EfficiencyTable::BoundType & val ) const
protected

Definition at line 1015 of file Database.cxx.

1016{
1017 #ifdef FAKEBKGTOOLS_ATLAS_ENVIRONMENT
1018 float energy_scale = (m_useGeV? 0.001f : 1.f);
1019 #else
1020 float energy_scale = 1;
1021 #endif
1022 if(param.level == Param::Level::PARTICLE)
1023 {
1024 if(param.type==Param::Type::PREDEFINED_FLOAT || param.type==Param::Type::PREDEFINED_INT)
1025 {
1026 if(param.name=="pt") val.as_float = energy_scale * p.pt();
1027 else if(param.name=="eta") val.as_float = p.eta();
1028 else if(param.name=="|eta|") val.as_float = fabs(p.eta());
1029 else if(param.name=="phi") val.as_float = p.phi();
1030 else return false;
1031 }
1032 else if(param.type == Param::Type::CUSTOM_FLOAT) {
1033 SG::ConstAccessor<float> acc(param.name);
1034 val.as_float = acc(p);
1035 }
1036 else if(param.type == Param::Type::CUSTOM_INT) {
1037 SG::ConstAccessor<int> acc(param.name);
1038 val.as_int = acc(p);
1039 }
1040 else return false;
1041 }
1042 else if(param.level == Param::Level::EVENT)
1043 {
1044 if (!eventInfo) {
1045 throw(GenericError() << "unexpected error: No EventInfo, but asked for event parameter");
1046 }
1047 if(param.type == Param::Type::CUSTOM_FLOAT) {
1048 SG::ConstAccessor<float> acc(param.name);
1049 val.as_float = acc(*eventInfo);
1050 }
1051 else if(param.type == Param::Type::CUSTOM_INT) {
1052 SG::ConstAccessor<int> acc(param.name);
1053 val.as_int = acc(*eventInfo);
1054 }
1055 else return false;
1056 }
1057 else return false;
1058 return true;
1059}
static const SG::AuxElement::Accessor< ElementLink< IParticleContainer > > acc("originalObjectLink")
Object used for setting/getting the dynamic decoration in question.

◆ selectEfficiency()

Efficiency * Database::selectEfficiency ( FakeBkgTools::ParticleData & pd,
const xAOD::IParticle & p,
EfficiencyType type )
staticprotected

Methods used to fill efficiencies.

Definition at line 1061 of file Database.cxx.

1062{
1063 switch(p.type())
1064 {
1066 if(type==ELECTRON_FAKE_FACTOR) return &pd.fake_factor;
1067 else if(type==ELECTRON_FAKE_EFFICIENCY) return &pd.fake_efficiency;
1068 else if(type==ELECTRON_REAL_EFFICIENCY) return &pd.real_efficiency;
1069 else if(type==PHOTON_ELE_FAKE_FACTOR) return &pd.fake_factor;
1070 break;
1071 case xAOD::Type::Muon:
1072 if(type==MUON_FAKE_FACTOR) return &pd.fake_factor;
1073 else if(type==MUON_FAKE_EFFICIENCY) return &pd.fake_efficiency;
1074 else if(type==MUON_REAL_EFFICIENCY) return &pd.real_efficiency;
1075 break;
1076 case xAOD::Type::Tau:
1077 if(type==TAU_FAKE_FACTOR) return &pd.fake_factor;
1078 else if(type==TAU_FAKE_EFFICIENCY) return &pd.fake_efficiency;
1079 else if(type==TAU_REAL_EFFICIENCY) return &pd.real_efficiency;
1080 break;
1081 case xAOD::Type::Photon:
1082 if(type==PHOTON_ELE_FAKE_FACTOR_SF) return &pd.fake_factor;
1083 break;
1084 default:;
1085 }
1086 return nullptr;
1087}
@ Photon
The object is a photon.
Definition ObjectType.h:47
@ Muon
The object is a muon.
Definition ObjectType.h:48
@ Electron
The object is an electron.
Definition ObjectType.h:46
@ Tau
The object is a tau (jet).
Definition ObjectType.h:49

◆ selectTypesToFill()

auto Database::selectTypesToFill ( Client client)
staticprotected

This function is only called by the Database constructor.

Definition at line 1090 of file Database.cxx.

1091{
1092 std::bitset<N_EFFICIENCY_TYPES> result;
1093 if(client==Client::MATRIX_METHOD || client==Client::ALL_METHODS)
1094 {
1101 }
1102 if(client==Client::FAKE_FACTOR || client==Client::ALL_METHODS)
1103 {
1105 result[MUON_FAKE_FACTOR] = true;
1106 result[TAU_FAKE_FACTOR] = true;
1107 }
1108 if(client==Client::E2Y_FAKE || client==Client::ALL_METHODS)
1109 {
1112 }
1113 if(result.none()) throw(GenericError() << "unrecognized client type, implementation incomplete");
1114 return result;
1115}

◆ statIndexToUID()

constexpr unsigned short FakeBkgTools::Database::statIndexToUID ( unsigned short index)
inlinestaticconstexpr

Definition at line 221 of file Database.h.

221{ return 0x8000 | index; }

◆ systIndexToUID()

constexpr unsigned short FakeBkgTools::Database::systIndexToUID ( unsigned short index)
inlinestaticconstexpr

Definition at line 220 of file Database.h.

220{ return 0x4000 | index; }

Member Data Documentation

◆ m_convertWhenMissing

const bool FakeBkgTools::Database::m_convertWhenMissing
protected

Definition at line 244 of file Database.h.

◆ m_lineOffset

std::vector<std::size_t> FakeBkgTools::Database::m_lineOffset
protected

Definition at line 255 of file Database.h.

◆ m_normFactors

std::map<std::string, float> FakeBkgTools::Database::m_normFactors
protected

Definition at line 256 of file Database.h.

◆ m_params

std::vector<Param> FakeBkgTools::Database::m_params
protected

Permanent buffers.

Definition at line 248 of file Database.h.

◆ m_stats

std::vector<StatDef> FakeBkgTools::Database::m_stats
protected

Definition at line 250 of file Database.h.

◆ m_storeAllUncertainties

bool FakeBkgTools::Database::m_storeAllUncertainties = true
protected

Definition at line 245 of file Database.h.

◆ m_systs

std::vector<SystDef> FakeBkgTools::Database::m_systs
protected

Definition at line 249 of file Database.h.

◆ m_tables

std::map<int, std::vector<EfficiencyTable> > FakeBkgTools::Database::m_tables
protected

Definition at line 251 of file Database.h.

◆ m_typesToFill

const std::bitset<N_EFFICIENCY_TYPES> FakeBkgTools::Database::m_typesToFill
protected

Definition at line 242 of file Database.h.

◆ m_useGeV

const bool FakeBkgTools::Database::m_useGeV
protected

Definition at line 241 of file Database.h.

◆ m_xmlBuffer

std::string FakeBkgTools::Database::m_xmlBuffer
protected

Temporary buffers (only used while importing data).

Definition at line 254 of file Database.h.


The documentation for this class was generated from the following files: