51 if(kv.second.size())
return true;
67 std::map<unsigned, EfficiencyTable::BoundType> cachedParamVals;
79 bool found_central =
false;
81 eff->uncertainties.clear();
91 for(
auto& table : relevantTables->second)
94 if(status < 0)
return false;
99 error =
"while retrieving " +
getTypeAsString(
type) +
", found two non-orthogonal tables providing the central value";
102 found_central =
true;
111 if(
type != wantedType)
113 if(eff == &pd.fake_factor)
115 float f = eff->nominal/(1.f-eff->nominal), k = pow(f/eff->nominal, 2);
117 for(
auto& kv : eff->uncertainties) kv.second *= k;
119 else if(eff == &pd.fake_efficiency)
121 float e = eff->nominal/(1.f+eff->nominal), k = pow(
e/eff->nominal, 2);
123 for(
auto& kv : eff->uncertainties) kv.second *= k;
134 for(
const auto& dim : table.m_dimensions)
136 auto& param =
m_params[dim.paramUID];
138 auto& val = ins.first->second;
143 error =
"can't retrieve value of parameter \"" + param.name +
"\"";
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)
155 bin =
bin * (dim.nBounds-1) + (ubound - first - 1);
157 if(
bin < 0)
return 0;
162 error =
"unknown table type (tool implementation incomplete!)";
165 auto&
ref = table.m_efficiencies[
bin];
166 for(
auto& kv : eff.uncertainties) kv.second *=
ref.nominal;
167 for(
auto& kv :
ref.uncertainties)
171 if(!eff.uncertainties.emplace(kv.first, eff.nominal*kv.second).second)
173 error =
"central values and corrections must use different systematic uncertainties";
178 eff.nominal *=
ref.nominal;
188 if (filename[0] !=
'/')
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;
200 xml.open(filename, std::ios_base::in);
201 if(!xml.is_open())
throw(
GenericError() <<
"unable to open file " << filename);
207 while(std::getline(xml, line))
209 while(line.length() && (line.back()==
'\n' || line.back()==
'\r')) line.pop_back();
221 while(stream.length())
224 if(tag==
"electron" || tag==
"muon" || tag==
"tau")
addTables(tag, attributes,
contents);
228 else throw(
XmlError(stream) <<
"unknown/unexpected XML tag \"" << tag.str() <<
"\"");
240 for(
auto& kv : attributes) kv.second.clear();
242 std::string pattern =
"^\\s*(<([[:alnum:]]+)((?:\\s+\\|?[_[:alnum:]]+\\|?\\s*=\\s*\"[_[:alnum:]\\s,-\\[\\]\\.\\|]+\")*)\\s*>)(.*?)</\\2>\\s*";
244 if(!std::regex_search(stream.ptr, stream.endptr, cmr, std::regex(pattern)))
247 throw(
XmlError(stream) <<
"unable to find next tag");
249 tag.set(stream.ptr+cmr.position(2), cmr.length(2));
253 auto cpos = cmr.size()-1;
254 contents.set(stream.ptr+cmr.position(cpos), cmr.length(cpos));
256 stream.ptr += cmr.length();
261 auto nAttr = std::count(stream.ptr, stream.endptr,
'=');
264 std::string pattern =
"";
265 for(
int i=0;i<nAttr;++i) pattern +=
"\\s+(\\|?[_[:alnum:]]+\\|?)\\s*=\\s*\"([_[:alnum:]\\s,-\\[\\]\\.\\|]+)\"";
268 if(!std::regex_match(stream.ptr, stream.endptr, cmr, std::regex(pattern)))
270 throw(
XmlError(stream) <<
"unexpected error (internal))");
272 for(
unsigned i=1;i<cmr.size();i+=2)
274 auto attr = cmr[i].str();
275 auto itr = attributes.find(tag +
'/' + attr);
276 if(itr == attributes.end())
278 throw(
XmlError(stream.ptr+cmr.position(i), attr.length()) <<
"invalid attribute \"" << attr <<
"\"");
282 throw(
XmlError(stream.ptr+cmr.position(i), attr.length()) <<
"empty value for attribute \"" << attr <<
"\"");
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));
292 std::regex rx(
"<!--.*?-->");
294 while(std::regex_search(buffer, smr, rx))
296 std::size_t pos = smr.position(0),
length = smr.length(), endpos = pos +
length;
299 if(offset > endpos) offset -=
length;
300 else if(offset > pos) offset = pos;
302 buffer = smr.prefix().str() + smr.suffix().str();
308 const std::vector<std::string> keys = {
"<efficiencies>",
"</efficiencies>"};
309 for(
const auto& key : keys)
312 while((ipos = buffer.find(key)) != std::string::npos)
314 buffer.erase(ipos, key.length()-1);
322 std::vector<std::string> words;
323 std::stringstream
ss(std::string(stream.ptr, stream.endptr));
325 while(std::getline(
ss, w,
','))
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)
331 throw(
XmlError(stream) <<
"this should be a comma-separated list of names");
333 words.push_back(w.substr(i, j-i+1));
338template<
typename ReturnValue>
341 if(attr.
str() ==
ref)
return rv;
342 throw(
XmlError(attr) <<
"unsupported parameter type \"" << attr.
str() <<
"\"");
345template<
typename ReturnValue,
typename...
Args>
348 if(attr.
str() ==
ref)
return rv;
352template<
typename ReturnValue,
typename...
Args>
355 std::string attrname = tag.str() +
"/" +
type;
356 auto& attr = attributes.at(attrname);
357 if(!attr)
throw(
XmlError(tag) <<
"unspecified value for attribute \"" <<
type <<
"\"");
363 auto type =
getAttribute(tag, attributes,
"type",
"int", Param::Type::CUSTOM_INT,
"float", Param::Type::CUSTOM_FLOAT);
373 attributes[
"bin/" +
name];
374 attributes[
"table/" +
name];
380 std::bitset<N_EFFICIENCY_TYPES> affects;
383 auto targetMatches = [&](
const char*
a,
const char* b) ->
bool
384 {
return target==
a || target==b || target==std::string(
a)+
'-'+b; };
388 if(targetMatches(
"tau",
"real-efficiency")) { affects.set(
TAU_REAL_EFFICIENCY); ++matched; }
391 if(targetMatches(
"tau",
"fake-efficiency")) { affects.set(
TAU_FAKE_EFFICIENCY); ++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");
397 if(affects.none())
throw(
XmlError(tag) <<
"missing or empty attribute \"affects\"");
401 if(std::any_of(
m_systs.begin(),
m_systs.end(), [&](
const SystDef& s){ return s.name==name && (affects&s.affects).any(); }))
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");
414 if(pos)
throw(
XmlError(pos) <<
"exceeded max number of statistical uncertainties");
415 else throw(
GenericError() <<
"exceeded max number of statistical uncertainties");
426 else if(particle ==
"electron")
type =
getAttribute(particle, attributes,
"type",
428 else if(particle ==
"tau")
type =
getAttribute(particle, attributes,
"type",
430 else throw(
XmlError(particle) <<
"unexpected error: unsupported particle type " << particle.str());
431 auto statMode = attributes.at(particle.str()+
"/stat") ?
getAttribute(particle, attributes,
"stat",
435 unsigned short globalStatUID = 0;
439 while(stream.length())
443 readNextTag(stream, tag, subattributes, subcontents);
444 const TH1* hist =
nullptr;
445 if(tag==
"bin" || tag==
"table" || tag==
"TH1")
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");
456 throw(
XmlError(norm) <<
"normalization of input histograms is only accepted for 'input=\"correction\"'");
458 importNominalTH1(hist,
type, subattributes.at(
"TH1/X"), subattributes.at(
"TH1/Y"), subattributes.at(
"TH1/Z"), scale, statMode, globalStatUID, subcontents);
462 table.inputType = inputType;
464 auto initialNumberOfBins = table.numberOfBins();
465 std::map<StringRef, unsigned> dimBins;
469 if(binning) dimBins.emplace(binning,
uid);
471 for(
auto& kv : dimBins)
addDimension(table, kv.second, kv.first);
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);
478 else if(table.numberOfBins() != initialNumberOfBins)
throw(
XmlError(tag) <<
"extra binned dimensions do not make sense");
479 if(tag==
"TH1" || tag==
"bin")
481 auto&
label = subattributes.at(tag +
"/label");
484 float normFactor {0};
488 assert (tag ==
"bin");
489 normFactor = 1.f / table.m_efficiencies[0].nominal;
491 if(!std::isnormal(normFactor) || normFactor<=0.)
throw(
XmlError(
label) <<
"computed normalization factor is 0 / NaN / infinite / negative");
497 else throw(
XmlError(tag) <<
"unknown/unexpected XML tag \"" << tag.str() <<
"\"");
507 std::getline(
ss, line);
508 throw(
XmlError(pos) <<
"unexpected parsing error (leftover data \"" << line <<
"\")");
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*$";
525 throw(
XmlError(
contents) <<
"invalid format for the range of the parameter " << param.name);
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();
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)
544 else ss >>
x.as_float;
547 if(i==0 || i==(dim.nBounds-1))
554 if(x_s==
"inf" || x_s==
"-inf")
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();
562 if(
ss.fail())
throw(
XmlError(
contents) <<
"parsing error (can't read int/float boundary)");
566 if(
integer ? (bounds.back().as_int >
x.as_int) : (bounds.back().as_float >
x.as_float))
568 throw(
XmlError(
contents) <<
"bin boundaries must be sorted in increasing order");
577 bounds.push_back(bounds.back());
578 bounds.back().as_int += 1;
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);
595 if(!std::regex_search(ptr,
contents.endptr,
cm, rxValidFormat))
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) <<
" [...]");
600 StringRef valref{ptr,
static_cast<std::size_t
>(
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 =
' ';
608 table.m_efficiencies.emplace_back();
609 auto& eff = table.m_efficiencies.back();
611 bool foundStat =
false;
612 for(
unsigned i=0;i<nErrs;++i)
619 if(c2==
'+' || c2==
'-')
621 ss >> c2 >> uncval.
up >> sysname;
624 uncval.
up *= 0.01f * eff.nominal;
631 ss >> uncval.
up >> c2;
634 uncval.
up *= 0.01f * eff.nominal;
637 ss >> uncval.
down >> sysname;
640 uncval.
down *= 0.01f * eff.nominal;
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");
648 uncval.
up = -uncval.
up;
653 if(sysname ==
"stat")
655 if(foundStat)
throw(
XmlError(valref) <<
"there can be only one source of statistical uncertainty per bin");
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");
668 if(!eff.uncertainties.emplace(
uid, uncval).second)
670 throw(
XmlError(valref) <<
"source of uncertainty \"" << sysname <<
"\" specified twice");
675 if(table.m_efficiencies.size() != table.numberOfBins())
677 throw(
XmlError(
contents) <<
"the number of tabulated efficiencies (" << table.m_efficiencies.size()
678 <<
") is inconsistent with the number of bins (" << table.numberOfBins() <<
")");
684 std::string filename = attributes.at(
"ROOT/source").str();
685 if(!filename.length())
throw(
XmlError(rootTag) <<
"the 'file' attribute must be specified!");
688 TFile*
file = TFile::Open(filename.c_str(),
"READ");
692 throw(
XmlError(rootTag) <<
"unable to locate/open the file " << filename);
697 while(stream.length())
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 <<
"\"");
711 attributes[
"ROOT/source"];
712 attributes[
"param/type"];
713 attributes[
"param/level"];
714 attributes[
"syst/affects"];
716 const std::vector<std::string> parts = {
"electron",
"muon",
"tau"};
717 for(
const auto& p : parts)
719 attributes[p +
"/type"];
720 attributes[p +
"/input"];
721 attributes[p +
"/stat"];
726 attributes[
"TH1/label"];
727 attributes[
"bin/label"];
728 attributes[
"TH1/norm"];
731 attributes[
"bin/" + p.name];
732 attributes[
"table/" + p.name];
733 attributes[
"TH1/" + p.name];
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);
750 if (filename[0] !=
'/')
753 TFile*
file = TFile::Open(filename.c_str(),
"READ");
756 throw(
GenericError() <<
"unable to locate/open the file " << filename);
759 auto keys =
file->GetListOfKeys();
760 if(!keys)
throw(
GenericError() <<
"unable to list keys in the file " << filename <<
" (corrupted?)");
763 unsigned short dummy;
764 for(
unsigned step=0;step<2;++step)
768 for(
int i=0;i<keys->GetSize();++i)
770 TKey* key =
static_cast<TKey*
>(keys->At(i));
772 std::string keyType = key->GetClassName();
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);
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();
788 bool systTH1 = (mr[mr.size()-1].
str() !=
"");
789 if(step==0 && !systTH1)
809 if(hist->GetNbinsX()!=1 || hist->GetNbinsY()!=1 || hist->GetNbinsZ()!=1)
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)
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");
825 if (denom > 0.) avg = sum / denom;
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");
836 if(!norm)
return 1.f;
837 auto normType = norm.str();
839 else if(normType !=
"none")
842 if(itr ==
m_normFactors.end())
throw(
XmlError(norm) <<
"unknown normalization tag \"" << normType <<
"\"");
849 float scale,
StatMode statMode,
unsigned short& globalStatUID,
const StringRef& xmlStream)
851 const bool useDefaults = !xmlStream;
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");
857 const int nDims = paramZ? 3 : paramY? 2 : 1;
858 if(hist->GetDimension() != nDims)
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");
865 for(
int j=0;j<nDims;++j)
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; });
882 else throw(
XmlError(j? paramY : paramX) <<
"parameter \"" <<
name <<
"\" has not been defined beforehand");
886 dim.paramUID = itr -
m_params.begin();
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)
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);
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();
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;
913 for(
unsigned z=1;
z<zmax;++
z)
915 table.m_efficiencies.emplace_back();
916 auto& eff = table.m_efficiencies.back();
917 eff.nominal = scale * hist->GetBinContent(
x,
y,
z);
921 float err = hist->GetBinError(
x,
y,
z);
923 eff.uncertainties.emplace(
uid, uncdata);
930 if(!
m_tables[
type].
size())
throw(
GenericError() <<
"there should be another histogram containing central values to accompany the histogram " << hist->GetName());
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)
937 throw(
GenericError() <<
"binning mismatch between the nominal histogram and " << hist->GetName());
941 auto itr = std::find_if(
m_systs.begin(),
m_systs.end(), [&](
const SystDef& sys){ return sys.name==sysname; });
945 itr->affects.set(
type);
956 bool syst_central_equal_nom_central =
true;
957 bool syst_errors_equal_zero =
true;
958 bool syst_errors_equal_nom_errors =
true;
960 auto eff = table.m_efficiencies.begin();
963 for(
int z=1;
z<zmax;++
z)
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;}
968 for(
auto& kv : eff->uncertainties)
971 stat_up = kv.second.up;
break;
973 if ( fabs((
float) hist->GetBinError(
x,
y,
z) - (
float) stat_up ) > 0.001) { syst_errors_equal_nom_errors =
false;}
978 eff = table.m_efficiencies.begin();
981 for(
int z=1;
z<zmax;++
z)
993 if (syst_central_equal_nom_central){
994 if (syst_errors_equal_nom_errors ){
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 ) {
997 err = hist->GetBinContent(
x,
y,
z);
999 err = hist->GetBinError(
x,
y,
z);
1002 err = hist->GetBinContent(
x,
y,
z);
1007 if(!eff->uncertainties.emplace(
uid, uncdata).second)
1009 throw(
GenericError() <<
"unexpected error: tried filling twice the same systematic");
1017 #ifdef FAKEBKGTOOLS_ATLAS_ENVIRONMENT
1018 float energy_scale = (
m_useGeV? 0.001f : 1.f);
1020 float energy_scale = 1;
1024 if(param.
type==Param::Type::PREDEFINED_FLOAT || param.
type==Param::Type::PREDEFINED_INT)
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();
1032 else if(param.
type == Param::Type::CUSTOM_FLOAT) {
1034 val.as_float =
acc(p);
1036 else if(param.
type == Param::Type::CUSTOM_INT) {
1038 val.as_int =
acc(p);
1045 throw(
GenericError() <<
"unexpected error: No EventInfo, but asked for event parameter");
1047 if(param.
type == Param::Type::CUSTOM_FLOAT) {
1049 val.as_float =
acc(*eventInfo);
1051 else if(param.
type == Param::Type::CUSTOM_INT) {
1053 val.as_int =
acc(*eventInfo);
1092 std::bitset<N_EFFICIENCY_TYPES> result;
1113 if(result.none())
throw(
GenericError() <<
"unrecognized client type, implementation incomplete");
1119 auto tables =
m_tables.find(wantedType);
1172 while(std::isspace(*beg) && beg<end) ++beg;
1173 while(std::isspace(*end) && end>beg) --end;
1174 return std::string(beg, end+1);
const std::regex ref(r_ef)
Helper class to provide constant type-safe access to aux data.
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
size_t size() const
Number of registered mappings.
Helper class to provide constant type-safe access to aux data.
Class providing the definition of the 4-vector interface.
void contents(std::vector< std::string > &keys, TDirectory *td, const std::string &directory, const std::string &pattern, const std::string &path)
std::string label(const std::string &format, int i)
Select isolated Photons, Electrons and Muons.
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.
@ Photon
The object is a photon.
@ Muon
The object is a muon.
@ Electron
The object is an electron.
@ Tau
The object is a tau (jet).
EventInfo_v1 EventInfo
Definition of the latest event info version.
static const SG::AuxElement::Accessor< ElementLink< IParticleContainer > > acc("originalObjectLink")
Object used for setting/getting the dynamic decoration in question.
c *Fortran *type rwl_lhe_block sequence integer rad_kinreg real aqcdup integer