36auto nth (
const CONT& c,
size_t n)
38 return *(c.begin() + n);
44TrigGlobalEfficiencyCorrectionTool::TrigGlobalEfficiencyCorrectionTool(
45 const std::string& name)
47 m_trigMatchTool(
"", nullptr),
48 m_checkElectronLegTag(false),
49 m_checkMuonLegTag(false),
51 m_validTrigMatchTool(false),
52 m_runNumberDecorator(
"RandomRunNumber"),
54 declareProperty(
"ElectronEfficiencyTools", m_suppliedElectronEfficiencyTools,
55 "electron MC efficiency tools (one for each kind of electron "
57 declareProperty(
"ElectronScaleFactorTools",
58 m_suppliedElectronScaleFactorTools,
59 "electron scale factor tools (one for each kind of electron "
62 "PhotonEfficiencyTools", m_suppliedPhotonEfficiencyTools,
63 "photon MC efficiency tools (one for each kind of photon trigger leg)");
65 "PhotonScaleFactorTools", m_suppliedPhotonScaleFactorTools,
66 "photon scale factor tools (one for each kind of photon trigger leg)");
67 declareProperty(
"MuonTools", m_suppliedMuonTools,
68 "muon efficiency/scale factor tool (one per year)");
69 declareProperty(
"ListOfLegsPerTool", m_legsPerTool,
70 "comma-separated list of trigger legs supported by each "
71 "electron or photon tool");
72 declareProperty(
"TriggerCombination", m_triggerCb,
73 "map of trigger combination per period and/or range of runs");
74 for (
int y : {15, 16, 17, 18, 22, 23, 24, 25, 26}) {
75 std::string
year = std::to_string(2000 +
y);
76 declareProperty(
"TriggerCombination" + year, m_triggerCbPerYear[year] =
"",
77 "trigger combination \"trigger1 || trigger2 || ...\"");
79 declareProperty(
"LeptonTagDecorations", m_leptonTagDecorations =
"",
80 "comma-separated list of decorations for the lepton "
81 "selection tags, ordered by increasing tightness. "
82 "If a name ends with =, the tag is the decorated value, "
83 "otherwise it is the decoration name");
85 "ListOfTagsPerTool", m_tagsPerTool,
86 "comma-separated list of lepton selection tags associated to each tool");
87 declareProperty(
"ElectronLegsPerTag", m_electronLegsPerTag,
88 "DEPRECATED, use ListOfLegsPerTag instead");
89 declareProperty(
"MuonLegsPerTag", m_muonLegsPerTag,
90 "DEPRECATED, use ListOfLegsPerTag instead");
91 declareProperty(
"ListOfLegsPerTag", m_legsPerTag,
92 "map of allowed trigger legs for each tag");
94 "NumberOfToys", m_numberOfToys = 0,
95 "if different from 0, use toy experiments instead of explicit formulas");
96 declareProperty(
"OverrideThresholds", m_overrideThresholds,
97 "new thresholds (in MeV) for the plateaux of the indicated "
98 "trigger legs -- use at your own risk!");
99 declareProperty(
"UseInternalSeed", m_useInternalSeed =
false,
100 "do not use event number as random number generation seed");
101 declareProperty(
"TriggerMatchingTool", m_trigMatchTool,
102 "handle to an IMatchingTool instance");
114 return StatusCode::FAILURE;
121 return StatusCode::FAILURE;
126 return StatusCode::FAILURE;
139 return StatusCode::FAILURE;
142 ATH_MSG_DEBUG(
"Retrieving trigger matching tool (if provided)");
147 return StatusCode::FAILURE;
156 return StatusCode::FAILURE;
166 collectedMuonTags) ||
171 return StatusCode::FAILURE;
183 bool useDefaultElectronTools =
191 useDefaultPhotonTools))
192 return StatusCode::FAILURE;
196 collectedPhotonTags))
197 return StatusCode::FAILURE;
201 return StatusCode::FAILURE;
205 return StatusCode::FAILURE;
209 return StatusCode::SUCCESS;
215 "The property 'ElectronLegsPerTag' is deprecated, please use "
216 "'ListOfLegsPerTag' instead");
220 insert.first->second +=
"," + kv.second;
225 "The property 'MuonLegsPerTag' is deprecated, please use "
226 "'ListOfLegsPerTag' instead");
230 insert.first->second +=
"," + kv.second;
239 const std::size_t star =
m_hasher(
"*");
241 allTags.insert((tag != star) ? tag : 0);
245 <<
"\" is not provided in a valid format");
250template <
class CPTool>
252 ImportData& data, ToolHandleArray<CPTool>& suppliedTools,
253 std::map<ToolKey, std::size_t>& toolIndex,
257 auto& handle = suppliedTools[
index];
258 const std::string& name = handle.name();
259 const std::string& altname = handle->name();
262 if (suppliedTools.size() != 1 ||
m_legsPerTool.size() != 0) {
270 "The 'ListOfLegsPerTool' property has an invalid entry for the "
275 }
else if (std::is_same<CPTool,
279 ATH_MSG_ERROR(
"Property 'ListOfLegsPerTool' empty for tool '" << name
284 listOfLegs.emplace();
287 listOfLegs.emplace();
295 collectedTags.insert(
tags.begin(),
tags.end());
300 unsigned short nUncheckedLegs = 0;
301 for (
auto& key : listOfLegs) {
302 std::size_t leg = key.hash;
304 auto flavour = data.associatedLeptonFlavour(leg, success);
316 for (std::size_t tag :
tags) {
317 if (!toolIndex.emplace(
ToolKey(leg, tag, key.boundaries),
index)
320 ATH_MSG_ERROR(
"Multiple tools associated to the selection tag '"
324 ATH_MSG_ERROR(
"Multiple tools associated to the trigger leg '"
327 ATH_MSG_ERROR(
"Multiple tools associated to the selection tag '"
331 "Multiple tools not associated to any trigger leg / selection "
338 if (!nUncheckedLegs) {
340 <<
" hasn't been associated to any trigger leg");
348 ImportData& data,
const std::string& inputList,
bool& success)
350 if (!inputList.length())
353 "\\s*([[:alnum:]_]+)\\s*(?:\\[\\s*([^,\\[\\]]+)\\s*\\]\\s*)?(?:,|$)");
356 auto itr = inputList.cbegin();
360 if (!std::regex_search(itr, inputList.cend(), sm, rx) ||
361 sm.prefix().length()) {
362 ATH_MSG_ERROR(
"Invalid format for the property \"ListOfLegsPerTool\"");
369 << sm[1].
str() <<
"' found in 'ListOfLegsPerTool'");
375 if (!data.getPeriodBoundaries(sm[2].str(), key.boundaries)) {
378 <<
"\"found in the property \"ListOfLegsPerTool\"");
383 if (!keys.emplace(key).second) {
386 <<
"' mentioned several times with overlapping time "
387 "periods in the property 'ListOfLegsPerTool'");
391 }
while (sm.suffix().length());
396 ImportData& data,
bool useDefaultElectronTools,
397 bool useDefaultPhotonTools) {
398 bool success =
true, mustBeEmpty =
m_triggerCb.size();
400 if (!kv.second.size())
404 "You're not allowed to use simultaneously the 'TriggerCombination' "
405 "and 'TriggerCombination"
406 << kv.first <<
"' properties.");
413 std::set<std::size_t> allUniqueElectronLegs, allUniquePhotonLegs;
415 std::pair<unsigned, unsigned> boundaries;
416 if (!data.getPeriodBoundaries(kv.first, boundaries)) {
420 std::size_t uniqueElectronLeg = !useDefaultElectronTools,
421 uniquePhotonLeg = !useDefaultPhotonTools;
423 uniqueElectronLeg, uniquePhotonLeg)) {
427 if (uniqueElectronLeg && useDefaultElectronTools)
428 allUniqueElectronLegs.insert(uniqueElectronLeg);
429 if (uniquePhotonLeg && useDefaultPhotonTools)
430 allUniquePhotonLegs.insert(uniquePhotonLeg);
435 auto remapTools = [](
auto& toolIndex,
auto& allUniqueLegs) {
436 typename std::remove_reference<
decltype(toolIndex)>
::type remappedToolIndex;
437 for (std::size_t leg : allUniqueLegs) {
440 for (
auto& kv : toolIndex) {
444 remappedToolIndex.emplace(
ToolKey(leg, key.hash, key.boundaries),
448 toolIndex.swap(remappedToolIndex);
451 if (useDefaultElectronTools && allUniqueElectronLegs.size()) {
455 if (useDefaultPhotonTools && allUniquePhotonLegs.size()) {
469 collectedTags.insert(collectedMuonTags.begin(), collectedMuonTags.end());
470 collectedTags.insert(collectedPhotonTags.begin(), collectedPhotonTags.end());
476 std::stringstream
ss(
478 std::string decoration;
480 while (std::getline(
ss, decoration,
',')) {
481 if (!decoration.length() || decoration ==
"?") {
483 "Found an empty string in the 'LeptonTagDecorations' property");
488 bool found =
false, suffixed =
false;
490 if (decoration.back() !=
'?') {
493 found = (allTags.find(
h) != allTags.end());
496 decoration.pop_back();
498 for (std::size_t tag :
502 if (s.find(decoration) != 0)
504 if (std::all_of(s.begin() + decoration.length(), s.end(),
505 [](
char c) { return std::isdigit(c); })) {
512 if (!allDecorations.insert(
h).second) {
514 "The selection tag '"
516 <<
"' is listed twice in the property 'LeptonTagDecorations'");
522 "the selection tag '"
524 <<
"' is only referred to in the property 'LeptonTagDecorations'");
537 for (std::size_t tag : collectedTags) {
543 return (!ltd.suffixed) && (ltd.hash == tag);
551 if (s.find(name) != 0)
553 if (std::all_of(s.begin() + name.length(), s.end(),
554 [](
char c) { return std::isdigit(c); })) {
562 <<
"' hasn't been found in in 'LeptonTagDecorations'");
580 if (!kv.first.size() || kv.first ==
"*")
587 "The property 'ListOfLegsPerTag' has an invalid entry for the tag '"
591 for (std::size_t leg : listOfLegs) {
597 ATH_MSG_ERROR(
"No electron tool has been provided for trigger leg '"
598 <<
m_dictionary[leg] <<
"' and selection tag " << kv.first
599 <<
" mentioned in the property 'ListOfLegsPerTag'");
604 ATH_MSG_ERROR(
"No muon tool has been provided for selection tag "
606 <<
" mentioned in the property 'ListOfLegsPerTag'");
611 ATH_MSG_ERROR(
"No photon tool has been provided for trigger leg '"
612 <<
m_dictionary[leg] <<
"' and selection tag " << kv.first
613 <<
" mentioned in the property 'ListOfLegsPerTag'");
625 <<
m_dictionary[leg] <<
"' and selection tag " << kv.first
626 <<
" is mentioned more than once in the property "
627 "'ListOfLegsPerTag'");
654 while (std::getline(
ss, token,
',')) {
655 if (token.length()) {
657 if (hashes.insert(
h).second) {
662 "Found duplicate entry while parsing comma-separated list '"
668 "Found null-length entry while parsing comma-separated list '"
677template <
class ParticleType>
679 const ParticleType* p,
unsigned runNumber, std::size_t leg, std::size_t tag,
683 return std::is_same<ParticleType, xAOD::Electron>::value ?
"electron"
684 : std::is_same<ParticleType, xAOD::Photon>::value ?
"photon"
689 << ptype() <<
' ' << p <<
" (pt=" << pp->pt()
690 <<
", eta=" << pp->eta() <<
", tag='" <<
m_dictionary[tag]
697 efficiencies.data() = 0.5;
698 efficiencies.mc() = 0.5;
703 << ptype() <<
" tools needed for trigger leg "
708 << ptype() <<
" tools needed for trigger leg "
717 .getEfficiencyScaleFactor(*p, sf)) &&
719 .getEfficiencyScaleFactor(*p, efficiencies.mc()));
720 efficiencies.data() = sf * efficiencies.mc();
722 <<
" eff(data) = " << efficiencies.data()
723 <<
" and eff(MC) = " << efficiencies.mc());
734 const xAOD::Photon* p,
unsigned runNumber, std::size_t leg, std::size_t tag,
740 const xAOD::Muon* p,
unsigned runNumber, std::size_t leg, std::size_t tag,
743 << p <<
" (pt=" << p->pt() <<
", eta=" << p->eta() <<
", tag='"
748 efficiencies.data() = 0.5;
749 efficiencies.mc() = 0.5;
757 ATH_MSG_ERROR(
"Unable to find muon tool needed for selection tag "
764 if (!hltTrig.size()) {
767 std::size_t i = hltTrig.find(
"_OR_m");
768 if (i == std::string::npos)
770 hltTrig.insert(i + 4,
"HLT_", 4);
773 bool success =
checkAndRecord(tool.getTriggerEfficiency(*p, efficiencies.mc(),
776 *p, efficiencies.data(), hltTrig, kTRUE));
777 ATH_MSG_DEBUG(
"found for that muon eff(data) = " << efficiencies.data()
779 << efficiencies.mc());
784 unsigned& runNumber) {
793 ATH_MSG_ERROR(
"Can't retrieve 'RandomRunNumber' from EventInfo");
798 runNumber = eventInfo->runNumber();
803 unsigned long& eventNumber) {
810 eventNumber = eventInfo->eventNumber();
814template <
class Particle>
816 LeptonList& leptons,
const std::vector<const Particle*>& particles) {
817 for (
auto lep : particles) {
820 if (ltd.decorator.isAvailable(*lep)) {
821 char v = ltd.decorator(*lep);
825 std::string s =
m_dictionary.at(ltd.hash) + std::to_string(v);
833 leptons.emplace_back(lep, tag);
839 const std::vector<const xAOD::IParticle*>& leptons,
840 double& efficiencyScaleFactor) {
848 const std::vector<const xAOD::IParticle*>& leptons,
double& efficiencyData,
849 double& efficiencyMc) {
853 return getEfficiency(runNumber, leptons, efficiencyData, efficiencyMc);
857 unsigned runNumber,
const std::vector<const xAOD::IParticle*>& particles,
858 double& efficiencyScaleFactor) {
861 efficiencyScaleFactor = 1.;
864 auto cc =
getEfficiency(runNumber, particles, efficiencies.data(),
867 if (efficiencies.data() > 0. && efficiencies.mc() > 0.) {
868 efficiencyScaleFactor = efficiencies.data() / efficiencies.mc();
871 efficiencyScaleFactor = 1.;
873 "Efficiencies do not seem valid, forcing the scale factor to 1.");
877 efficiencyScaleFactor = 1.;
882 unsigned runNumber,
const std::vector<const xAOD::IParticle*>& particles,
883 double& efficiencyData,
double& efficiencyMc) {
889 ATH_MSG_DEBUG(
"Computing global trigger efficiency for this event with "
891 <<
" lepton(s) as input; run number = " << runNumber);
893#ifdef XAOD_STANDALONE
908 if (
m_calculator->compute(*
this, leptons, runNumber, efficiencies)) {
909 efficiencyData = efficiencies.data();
910 efficiencyMc = efficiencies.mc();
911 if (std::isnan(efficiencies.data()) || efficiencies.data() <= 0. ||
912 std::isnan(efficiencies.mc()) || efficiencies.mc() <= 0.) {
927 const std::vector<const xAOD::IParticle*>& particles) {
931 "Unable to retrieve run number, aborting checkTriggerMatching()");
936 "A valid IMatchingTool instance should be provided via the property "
937 "'TriggerMatchingTool'");
942 return m_calculator->checkTriggerMatching(*
this, matched,
nullptr, leptons, runNumber)
948 std::unordered_map<std::string, bool>& matched_per_trigger,
949 const std::vector<const xAOD::IParticle*>& particles) {
953 "Unable to retrieve run number, aborting checkTriggerMatching()");
958 "A valid IMatchingTool instance should be provided via the property "
959 "'TriggerMatchingTool'");
965 return m_calculator->checkTriggerMatching(*
this, flag, &matched_per_trigger, leptons, runNumber)
971 std::vector<std::string>& triggers) {
975 "Unable to retrieve run number, aborting getRelevantTriggers()");
978 return m_calculator->getRelevantTriggersForUser(*
this, triggers, runNumber)
984 const std::string& trigger, std::size_t& numberOfLegs) {
990 constexpr std::size_t magic = 0xa3bad03e613527c9;
991 const std::size_t name =
m_hasher(trigger), key = name ^ magic;
993 if (!value.length()) {
995 if (!data.importTriggers())
997 auto itr = data.getTriggerDefs().find(name);
998 if (itr == data.getTriggerDefs().end()) {
1000 ATH_MSG_ERROR(
"The trigger " << trigger <<
" is not recognized");
1005 if (
type & TriggerType::TT_SINGLELEPTON_FLAG)
1007 else if (
type & TriggerType::TT_DILEPTON_FLAG)
1009 else if (
type & TriggerType::TT_TRILEPTON_FLAG)
1013 ATH_MSG_ERROR(
"Unrecognized trigger type, implementation must be fixed!");
1017 numberOfLegs = value.length();
1022 std::size_t leg)
const {
1033 <<
") is " << (decision ?
"" :
"not ")
1034 <<
"considered suitable for firing trigger leg "
1041 if (legs.size() < 2)
1043 std::size_t combinedHash = 0;
1044 for (
auto& leg : legs)
1045 combinedHash ^= leg;
1046 return combinedHash;
1050 std::size_t leg1, std::size_t leg2) {
1060inline constexpr std::array<std::size_t, 2>
1064 return {leg1, leg2};
1066 return {leg2, leg1};
1069template <
class... ListOfLegs>
1071 const Lepton& lepton, ListOfLegs... legs) {
1074 return 0xFEDCBA9876543210;
1076 auto rankingItr = cachedRankings.first;
1077 float pt = lepton.
pt();
1078 while (rankingItr != cachedRankings.second &&
1079 (pt < rankingItr->second.minPt || pt >= rankingItr->second.maxPt))
1081 if (rankingItr == cachedRankings.second) {
1087 return rankingItr->second.ranking;
1090template <
class Container>
1094 const std::size_t nLegs = legs.size();
1096 r.ranking = std::numeric_limits<
decltype(
r.ranking)>
::max();
1098 r.maxPt = std::numeric_limits<float>::max();
1099 if (nLegs >= 2 *
sizeof(
r.ranking)) {
1101 "Implementation currently doesn't support ranking of more than "
1102 << 2 *
sizeof(
r.ranking) <<
" trigger legs");
1105 std::vector<uint8_t> counts(nLegs);
1110 auto legI = legs.begin();
1111 for (
unsigned i = 0; i < nLegs; ++i) {
1113 for (
unsigned j = i + 1; j < nLegs; ++j) {
1117 if (pt < meta.minPt || pt >=
meta.maxPt)
1120 auto end = data +
meta.nLegs;
1121 auto a = std::find(data, end, *legI);
1124 auto b = std::find(data, end, *legJ);
1127 r.minPt = std::max(
r.minPt,
meta.minPt);
1128 r.maxPt = std::min(
r.maxPt,
meta.maxPt);
1129 ++(counts[(
a > b) ? i : j]);
1143 decltype(
r.ranking) ranking = 0;
1144 for (
unsigned i = 0; i < nLegs; ++i) {
1145 unsigned char index =
1146 std::find(counts.begin(), counts.end(), i) - counts.begin();
1147 if (
index >= nLegs) {
1149 << nLegs <<
" trigger legs");
1152 ranking = (ranking << 4 |
index);
1154 r.ranking = ranking;
1159 const Lepton& lepton, std::size_t leg1, std::size_t leg2,
bool& success) {
1168std::pair<std::size_t, std::size_t>
1176 std::pair<std::size_t, std::size_t> looseLegs{0, 0};
1177 looseLegs.first = nth (legs, ranking & 0xF);
1178 if (legs.size() >= 2)
1179 looseLegs.second = nth (legs, (ranking >> 4) & 0xF);
1186 for (
auto leg : legs)
1188 validLegs.insert(leg);
1189 if (validLegs.size() == 0)
1191 if (validLegs.size() == 1)
1192 return *validLegs.begin();
1198 return nth (legs, ranking & 0xF);
1203 const int nLegs = legs.size();
1207 ranking = 0xFEDCBA9876543210;
1209 std::vector<std::size_t> sorted_legs(nLegs);
1210 for (
int i = 0; i < nLegs; ++i) {
1211 sorted_legs[i] = nth (legs, ranking & 0xF);
1218 const std::map<std::string, std::string>& triggerCombination,
1219 const std::string& version, std::map<std::string, std::string>& legsPerKey,
1223 data.suggestEgammaMapKeys(triggerCombination, version, legsPerKey,
type);
1230 return !systematic.
empty() && sys.find(systematic) != sys.end();
1246 ANA_CHECK(t->applySystematicVariation(systematic));
1248 ANA_CHECK(t->applySystematicVariation(systematic));
1250 ANA_CHECK(t->applySystematicVariation(systematic));
1252 ANA_CHECK(t->applySystematicVariation(systematic));
1254 ANA_CHECK(t->applySystematicVariation(systematic));
1256 return StatusCode::SUCCESS;
#define ATH_MSG_WARNING(x)
TrigGlobEffCorr::ImportData ImportData
TrigGlobEffCorr::CheckConfig CheckConfig
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