33TrigGlobalEfficiencyCorrectionTool::TrigGlobalEfficiencyCorrectionTool(
34 const std::string& name)
36 m_trigMatchTool(
"", nullptr),
37 m_checkElectronLegTag(false),
38 m_checkMuonLegTag(false),
40 m_validTrigMatchTool(false),
41 m_runNumberDecorator(
"RandomRunNumber"),
43 declareProperty(
"ElectronEfficiencyTools", m_suppliedElectronEfficiencyTools,
44 "electron MC efficiency tools (one for each kind of electron "
46 declareProperty(
"ElectronScaleFactorTools",
47 m_suppliedElectronScaleFactorTools,
48 "electron scale factor tools (one for each kind of electron "
51 "PhotonEfficiencyTools", m_suppliedPhotonEfficiencyTools,
52 "photon MC efficiency tools (one for each kind of photon trigger leg)");
54 "PhotonScaleFactorTools", m_suppliedPhotonScaleFactorTools,
55 "photon scale factor tools (one for each kind of photon trigger leg)");
56 declareProperty(
"MuonTools", m_suppliedMuonTools,
57 "muon efficiency/scale factor tool (one per year)");
58 declareProperty(
"ListOfLegsPerTool", m_legsPerTool,
59 "comma-separated list of trigger legs supported by each "
60 "electron or photon tool");
61 declareProperty(
"TriggerCombination", m_triggerCb,
62 "map of trigger combination per period and/or range of runs");
63 for (
int y : {15, 16, 17, 18, 22, 23, 24, 25, 26}) {
64 std::string year = std::to_string(2000 +
y);
65 declareProperty(
"TriggerCombination" + year, m_triggerCbPerYear[year] =
"",
66 "trigger combination \"trigger1 || trigger2 || ...\"");
68 declareProperty(
"LeptonTagDecorations", m_leptonTagDecorations =
"",
69 "comma-separated list of decorations for the lepton "
70 "selection tags, ordered by increasing tightness. "
71 "If a name ends with =, the tag is the decorated value, "
72 "otherwise it is the decoration name");
74 "ListOfTagsPerTool", m_tagsPerTool,
75 "comma-separated list of lepton selection tags associated to each tool");
76 declareProperty(
"ElectronLegsPerTag", m_electronLegsPerTag,
77 "DEPRECATED, use ListOfLegsPerTag instead");
78 declareProperty(
"MuonLegsPerTag", m_muonLegsPerTag,
79 "DEPRECATED, use ListOfLegsPerTag instead");
80 declareProperty(
"ListOfLegsPerTag", m_legsPerTag,
81 "map of allowed trigger legs for each tag");
83 "NumberOfToys", m_numberOfToys = 0,
84 "if different from 0, use toy experiments instead of explicit formulas");
85 declareProperty(
"OverrideThresholds", m_overrideThresholds,
86 "new thresholds (in MeV) for the plateaux of the indicated "
87 "trigger legs -- use at your own risk!");
88 declareProperty(
"UseInternalSeed", m_useInternalSeed =
false,
89 "do not use event number as random number generation seed");
90 declareProperty(
"TriggerMatchingTool", m_trigMatchTool,
91 "handle to an IMatchingTool instance");
103 return StatusCode::FAILURE;
110 return StatusCode::FAILURE;
115 return StatusCode::FAILURE;
128 return StatusCode::FAILURE;
131 ATH_MSG_DEBUG(
"Retrieving trigger matching tool (if provided)");
136 return StatusCode::FAILURE;
145 return StatusCode::FAILURE;
155 collectedMuonTags) ||
160 return StatusCode::FAILURE;
172 bool useDefaultElectronTools =
180 useDefaultPhotonTools))
181 return StatusCode::FAILURE;
185 collectedPhotonTags))
186 return StatusCode::FAILURE;
190 return StatusCode::FAILURE;
194 return StatusCode::FAILURE;
198 return StatusCode::SUCCESS;
204 "The property 'ElectronLegsPerTag' is deprecated, please use "
205 "'ListOfLegsPerTag' instead");
209 insert.first->second +=
"," + kv.second;
214 "The property 'MuonLegsPerTag' is deprecated, please use "
215 "'ListOfLegsPerTag' instead");
219 insert.first->second +=
"," + kv.second;
228 const std::size_t star =
m_hasher(
"*");
230 allTags.insert((tag != star) ? tag : 0);
234 <<
"\" is not provided in a valid format");
239template <
class CPTool>
242 std::map<ToolKey, std::size_t>& toolIndex,
246 auto& handle = suppliedTools[
index];
247 const std::string& name = handle.name();
248 const std::string& altname = handle->name();
251 if (suppliedTools.size() != 1 ||
m_legsPerTool.size() != 0) {
259 "The 'ListOfLegsPerTool' property has an invalid entry for the "
264 }
else if (std::is_same<CPTool,
268 ATH_MSG_ERROR(
"Property 'ListOfLegsPerTool' empty for tool '" << name
273 listOfLegs.emplace();
276 listOfLegs.emplace();
284 collectedTags.insert(
tags.begin(),
tags.end());
289 unsigned short nUncheckedLegs = 0;
290 for (
auto& key : listOfLegs) {
291 std::size_t leg = key.hash;
293 auto flavour =
data.associatedLeptonFlavour(leg, success);
305 for (std::size_t tag :
tags) {
306 if (!toolIndex.emplace(
ToolKey(leg, tag, key.boundaries),
index)
309 ATH_MSG_ERROR(
"Multiple tools associated to the selection tag '"
313 ATH_MSG_ERROR(
"Multiple tools associated to the trigger leg '"
316 ATH_MSG_ERROR(
"Multiple tools associated to the selection tag '"
320 "Multiple tools not associated to any trigger leg / selection "
327 if (!nUncheckedLegs) {
329 <<
" hasn't been associated to any trigger leg");
339 if (!inputList.length())
342 "\\s*([[:alnum:]_]+)\\s*(?:\\[\\s*([^,\\[\\]]+)\\s*\\]\\s*)?(?:,|$)");
345 auto itr = inputList.cbegin();
349 if (!std::regex_search(itr, inputList.cend(), sm, rx) ||
350 sm.prefix().length()) {
351 ATH_MSG_ERROR(
"Invalid format for the property \"ListOfLegsPerTool\"");
358 << sm[1].
str() <<
"' found in 'ListOfLegsPerTool'");
364 if (!
data.getPeriodBoundaries(sm[2].str(), key.boundaries)) {
367 <<
"\"found in the property \"ListOfLegsPerTool\"");
372 if (!keys.emplace(key).second) {
375 <<
"' mentioned several times with overlapping time "
376 "periods in the property 'ListOfLegsPerTool'");
380 }
while (sm.suffix().length());
386 bool useDefaultPhotonTools) {
387 bool success =
true, mustBeEmpty =
m_triggerCb.size();
389 if (!kv.second.size())
393 "You're not allowed to use simultaneously the 'TriggerCombination' "
394 "and 'TriggerCombination"
395 << kv.first <<
"' properties.");
402 std::set<std::size_t> allUniqueElectronLegs, allUniquePhotonLegs;
404 std::pair<unsigned, unsigned> boundaries;
405 if (!
data.getPeriodBoundaries(kv.first, boundaries)) {
409 std::size_t uniqueElectronLeg = !useDefaultElectronTools,
410 uniquePhotonLeg = !useDefaultPhotonTools;
412 uniqueElectronLeg, uniquePhotonLeg)) {
416 if (uniqueElectronLeg && useDefaultElectronTools)
417 allUniqueElectronLegs.insert(uniqueElectronLeg);
418 if (uniquePhotonLeg && useDefaultPhotonTools)
419 allUniquePhotonLegs.insert(uniquePhotonLeg);
424 auto remapTools = [](
auto& toolIndex,
auto& allUniqueLegs) {
425 typename std::remove_reference<
decltype(toolIndex)>
::type remappedToolIndex;
426 for (std::size_t leg : allUniqueLegs) {
429 for (
auto& kv : toolIndex) {
433 remappedToolIndex.emplace(
ToolKey(leg, key.hash, key.boundaries),
437 toolIndex.swap(remappedToolIndex);
440 if (useDefaultElectronTools && allUniqueElectronLegs.size()) {
444 if (useDefaultPhotonTools && allUniquePhotonLegs.size()) {
458 collectedTags.insert(collectedMuonTags.begin(), collectedMuonTags.end());
459 collectedTags.insert(collectedPhotonTags.begin(), collectedPhotonTags.end());
465 std::stringstream
ss(
467 std::string decoration;
469 while (std::getline(
ss, decoration,
',')) {
470 if (!decoration.length() || decoration ==
"?") {
472 "Found an empty string in the 'LeptonTagDecorations' property");
477 bool found =
false, suffixed =
false;
479 if (decoration.back() !=
'?') {
482 found = (allTags.find(
h) != allTags.end());
485 decoration.pop_back();
487 for (std::size_t tag :
491 if (s.find(decoration) != 0)
493 if (std::all_of(s.begin() + decoration.length(), s.end(),
494 [](
char c) { return std::isdigit(c); })) {
501 if (!allDecorations.insert(
h).second) {
503 "The selection tag '"
505 <<
"' is listed twice in the property 'LeptonTagDecorations'");
511 "the selection tag '"
513 <<
"' is only referred to in the property 'LeptonTagDecorations'");
526 for (std::size_t tag : collectedTags) {
532 return (!ltd.suffixed) && (ltd.hash == tag);
540 if (s.find(name) != 0)
542 if (std::all_of(s.begin() + name.length(), s.end(),
543 [](
char c) { return std::isdigit(c); })) {
551 <<
"' hasn't been found in in 'LeptonTagDecorations'");
569 if (!kv.first.size() || kv.first ==
"*")
576 "The property 'ListOfLegsPerTag' has an invalid entry for the tag '"
580 for (std::size_t leg : listOfLegs) {
586 ATH_MSG_ERROR(
"No electron tool has been provided for trigger leg '"
587 <<
m_dictionary[leg] <<
"' and selection tag " << kv.first
588 <<
" mentioned in the property 'ListOfLegsPerTag'");
593 ATH_MSG_ERROR(
"No muon tool has been provided for selection tag "
595 <<
" mentioned in the property 'ListOfLegsPerTag'");
600 ATH_MSG_ERROR(
"No photon tool has been provided for trigger leg '"
601 <<
m_dictionary[leg] <<
"' and selection tag " << kv.first
602 <<
" mentioned in the property 'ListOfLegsPerTag'");
614 <<
m_dictionary[leg] <<
"' and selection tag " << kv.first
615 <<
" is mentioned more than once in the property "
616 "'ListOfLegsPerTag'");
643 while (std::getline(
ss, token,
',')) {
644 if (token.length()) {
646 if (hashes.insert(
h).second) {
651 "Found duplicate entry while parsing comma-separated list '"
657 "Found null-length entry while parsing comma-separated list '"
666template <
class ParticleType>
668 const ParticleType* p,
unsigned runNumber, std::size_t leg, std::size_t tag,
672 return std::is_same<ParticleType, xAOD::Electron>::value ?
"electron"
673 : std::is_same<ParticleType, xAOD::Photon>::value ?
"photon"
678 << ptype() <<
' ' << p <<
" (pt=" << pp->pt()
679 <<
", eta=" << pp->eta() <<
", tag='" <<
m_dictionary[tag]
686 efficiencies.data() = 0.5;
687 efficiencies.mc() = 0.5;
692 << ptype() <<
" tools needed for trigger leg "
697 << ptype() <<
" tools needed for trigger leg "
706 .getEfficiencyScaleFactor(*p, sf)) &&
708 .getEfficiencyScaleFactor(*p, efficiencies.mc()));
709 efficiencies.data() = sf * efficiencies.mc();
711 <<
" eff(data) = " << efficiencies.data()
712 <<
" and eff(MC) = " << efficiencies.mc());
723 const xAOD::Photon* p,
unsigned runNumber, std::size_t leg, std::size_t tag,
729 const xAOD::Muon* p,
unsigned runNumber, std::size_t leg, std::size_t tag,
732 << p <<
" (pt=" << p->pt() <<
", eta=" << p->eta() <<
", tag='"
737 efficiencies.data() = 0.5;
738 efficiencies.mc() = 0.5;
746 ATH_MSG_ERROR(
"Unable to find muon tool needed for selection tag "
753 if (!hltTrig.size()) {
756 std::size_t i = hltTrig.find(
"_OR_m");
757 if (i == std::string::npos)
759 hltTrig.insert(i + 4,
"HLT_", 4);
762 bool success =
checkAndRecord(tool.getTriggerEfficiency(*p, efficiencies.mc(),
765 *p, efficiencies.data(), hltTrig, kTRUE));
766 ATH_MSG_DEBUG(
"found for that muon eff(data) = " << efficiencies.data()
768 << efficiencies.mc());
773 unsigned& runNumber) {
782 ATH_MSG_ERROR(
"Can't retrieve 'RandomRunNumber' from EventInfo");
787 runNumber = eventInfo->runNumber();
792 unsigned long& eventNumber) {
799 eventNumber = eventInfo->eventNumber();
803template <
class Particle>
805 LeptonList& leptons,
const std::vector<const Particle*>& particles) {
806 for (
auto lep : particles) {
809 if (ltd.decorator.isAvailable(*lep)) {
810 char v = ltd.decorator(*lep);
814 std::string s =
m_dictionary.at(ltd.hash) + std::to_string(v);
822 leptons.emplace_back(lep, tag);
828 const std::vector<const xAOD::IParticle*>& leptons,
829 double& efficiencyScaleFactor) {
837 const std::vector<const xAOD::IParticle*>& leptons,
double& efficiencyData,
838 double& efficiencyMc) {
842 return getEfficiency(runNumber, leptons, efficiencyData, efficiencyMc);
846 unsigned runNumber,
const std::vector<const xAOD::IParticle*>& particles,
847 double& efficiencyScaleFactor) {
850 efficiencyScaleFactor = 1.;
853 auto cc =
getEfficiency(runNumber, particles, efficiencies.data(),
856 if (efficiencies.data() > 0. && efficiencies.mc() > 0.) {
857 efficiencyScaleFactor = efficiencies.data() / efficiencies.mc();
860 efficiencyScaleFactor = 1.;
862 "Efficiencies do not seem valid, forcing the scale factor to 1.");
866 efficiencyScaleFactor = 1.;
871 unsigned runNumber,
const std::vector<const xAOD::IParticle*>& particles,
872 double& efficiencyData,
double& efficiencyMc) {
878 ATH_MSG_DEBUG(
"Computing global trigger efficiency for this event with "
880 <<
" lepton(s) as input; run number = " << runNumber);
882#ifdef XAOD_STANDALONE
897 if (
m_calculator->compute(*
this, leptons, runNumber, efficiencies)) {
898 efficiencyData = efficiencies.data();
899 efficiencyMc = efficiencies.mc();
900 if (std::isnan(efficiencies.data()) || efficiencies.data() <= 0. ||
901 std::isnan(efficiencies.mc()) || efficiencies.mc() <= 0.) {
916 const std::vector<const xAOD::IParticle*>& particles) {
920 "Unable to retrieve run number, aborting checkTriggerMatching()");
925 "A valid IMatchingTool instance should be provided via the property "
926 "'TriggerMatchingTool'");
931 return m_calculator->checkTriggerMatching(*
this, matched,
nullptr, leptons, runNumber)
937 std::unordered_map<std::string, bool>& matched_per_trigger,
938 const std::vector<const xAOD::IParticle*>& particles) {
942 "Unable to retrieve run number, aborting checkTriggerMatching()");
947 "A valid IMatchingTool instance should be provided via the property "
948 "'TriggerMatchingTool'");
954 return m_calculator->checkTriggerMatching(*
this, flag, &matched_per_trigger, leptons, runNumber)
960 std::vector<std::string>& triggers) {
964 "Unable to retrieve run number, aborting getRelevantTriggers()");
967 return m_calculator->getRelevantTriggersForUser(*
this, triggers, runNumber)
973 const std::string& trigger, std::size_t& numberOfLegs) {
979 constexpr std::size_t magic = 0xa3bad03e613527c9;
980 const std::size_t name =
m_hasher(trigger), key = name ^ magic;
982 if (!value.length()) {
984 if (!
data.importTriggers())
986 auto itr =
data.getTriggerDefs().find(name);
987 if (itr ==
data.getTriggerDefs().end()) {
989 ATH_MSG_ERROR(
"The trigger " << trigger <<
" is not recognized");
994 if (
type & TriggerType::TT_SINGLELEPTON_FLAG)
996 else if (
type & TriggerType::TT_DILEPTON_FLAG)
998 else if (
type & TriggerType::TT_TRILEPTON_FLAG)
1002 ATH_MSG_ERROR(
"Unrecognized trigger type, implementation must be fixed!");
1006 numberOfLegs = value.length();
1011 std::size_t leg)
const {
1022 <<
") is " << (decision ?
"" :
"not ")
1023 <<
"considered suitable for firing trigger leg "
1030 if (legs.size() < 2)
1032 std::size_t combinedHash = 0;
1033 for (
auto& leg : legs)
1034 combinedHash ^= leg;
1035 return combinedHash;
1039 std::size_t leg1, std::size_t leg2) {
1049inline constexpr std::array<std::size_t, 2>
1053 return {leg1, leg2};
1055 return {leg2, leg1};
1058template <
class... ListOfLegs>
1060 const Lepton& lepton, ListOfLegs... legs) {
1063 return 0xFEDCBA9876543210;
1065 auto rankingItr = cachedRankings.first;
1066 float pt = lepton.
pt();
1067 while (rankingItr != cachedRankings.second &&
1068 (pt < rankingItr->second.minPt || pt >= rankingItr->second.maxPt))
1070 if (rankingItr == cachedRankings.second) {
1076 return rankingItr->second.ranking;
1079template <
class Container>
1083 const std::size_t nLegs = legs.size();
1085 r.ranking = std::numeric_limits<
decltype(
r.ranking)>
::max();
1087 r.maxPt = std::numeric_limits<float>::max();
1088 if (nLegs >= 2 *
sizeof(
r.ranking)) {
1090 "Implementation currently doesn't support ranking of more than "
1091 << 2 *
sizeof(
r.ranking) <<
" trigger legs");
1094 std::vector<uint8_t> counts(nLegs);
1099 auto legI = legs.begin();
1100 for (
unsigned i = 0; i < nLegs; ++i) {
1102 for (
unsigned j = i + 1; j < nLegs; ++j) {
1106 if (pt < meta.minPt || pt >=
meta.maxPt)
1110 auto a = std::find(
data, end, *legI);
1113 auto b = std::find(
data, end, *legJ);
1116 r.minPt = std::max(
r.minPt,
meta.minPt);
1117 r.maxPt = std::min(
r.maxPt,
meta.maxPt);
1118 ++(counts[(
a > b) ? i : j]);
1132 decltype(
r.ranking) ranking = 0;
1133 for (
unsigned i = 0; i < nLegs; ++i) {
1134 unsigned char index =
1135 std::find(counts.begin(), counts.end(), i) - counts.begin();
1136 if (
index >= nLegs) {
1138 << nLegs <<
" trigger legs");
1141 ranking = (ranking << 4 |
index);
1143 r.ranking = ranking;
1148 const Lepton& lepton, std::size_t leg1, std::size_t leg2,
bool& success) {
1157std::pair<std::size_t, std::size_t>
1165 std::pair<std::size_t, std::size_t> looseLegs{0, 0};
1166 looseLegs.first = *legs.nth(ranking & 0xF);
1167 if (legs.size() >= 2)
1168 looseLegs.second = *legs.nth((ranking >> 4) & 0xF);
1175 for (
auto leg : legs)
1177 validLegs.insert(leg);
1178 if (validLegs.size() == 0)
1180 if (validLegs.size() == 1)
1181 return *validLegs.begin();
1187 return *legs.nth(ranking & 0xF);
1192 const int nLegs = legs.size();
1196 ranking = 0xFEDCBA9876543210;
1198 std::vector<std::size_t> sorted_legs(nLegs);
1199 for (
int i = 0; i < nLegs; ++i) {
1200 sorted_legs[i] = *legs.nth(ranking & 0xF);
1207 const std::map<std::string, std::string>& triggerCombination,
1208 const std::string& version, std::map<std::string, std::string>& legsPerKey,
1212 data.suggestEgammaMapKeys(triggerCombination, version, legsPerKey,
type);
1219 return !systematic.
empty() && sys.find(systematic) != sys.end();
1235 ANA_CHECK(t->applySystematicVariation(systematic));
1237 ANA_CHECK(t->applySystematicVariation(systematic));
1239 ANA_CHECK(t->applySystematicVariation(systematic));
1241 ANA_CHECK(t->applySystematicVariation(systematic));
1243 ANA_CHECK(t->applySystematicVariation(systematic));
1245 return StatusCode::SUCCESS;
#define ATH_MSG_WARNING(x)
TrigGlobEffCorr::ImportData ImportData
TrigGlobEffCorr::CheckConfig CheckConfig
char data[hepevt_bytes_allocation_ATLAS]
ServiceHandle< StoreGateSvc > & evtStore()
Header file for AthHistogramAlgorithm.
Return value from object correction CP tools.
@ Error
Some error happened during the object correction.
@ OutOfValidityRange
Input object is out of validity range.
@ Ok
The correction was done successfully.
Class to wrap a set of SystematicVariations.
bool empty() const
returns: whether this is an empty systematic, i.e.
storage of the time histories of all the cells
bool advancedConfigChecks()
xAOD::Type::ObjectType associatedLeptonFlavour(std::size_t leg, bool &success)
const xAOD::IParticle * particle() const
xAOD::Type::ObjectType type() const
@ IS_SIMULATION
true: simulation, false: data
Class providing the definition of the 4-vector interface.
std::vector< std::string > tags
std::string removeWhitespaces(const std::string &s)
void reverse(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of reverse for DataVector/List.
ObjectType
Type of objects that have a representation in the xAOD EDM.
@ Photon
The object is a photon.
@ Muon
The object is a muon.
@ Electron
The object is an electron.
EventInfo_v1 EventInfo
Definition of the latest event info version.
Muon_v1 Muon
Reference the current persistent version:
Photon_v1 Photon
Definition of the current "egamma version".
Electron_v1 Electron
Definition of the current "egamma version".
ElementLink_p1< typename GenerateELinkIndexType_p1< typename LINK::index_type >::type > type