ATLAS Offline Software
Loading...
Searching...
No Matches
L1DataConsistencyChecker.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4// Local includes
7// Trigger includes
11// Athena includes
14// System includes
15#include <unordered_map>
16#include <sstream>
17
18namespace{
19 // this can be constexpr in C++20
20 bool vectorContains(const std::vector<std::string>& vec, const std::string& str) {
21 return (std::find(vec.cbegin(),vec.cend(),str)!=vec.cend());
22 }
23}
24
25// =============================================================================
27 ATH_CHECK(m_hltMenuKey.initialize());
28 ATH_CHECK(m_l1MenuKey.initialize());
29 if (!m_monTool.empty()) {
30 ATH_CHECK(m_monTool.retrieve());
31 }
32 return StatusCode::SUCCESS;
33}
34
35// =============================================================================
38 ATH_CHECK(l1Menu.isValid());
40 ATH_CHECK(hltMenu.isValid());
41
42 TrigConf::LogicParser logicParser;
43
44 m_thresholdMap.clear();
45 m_thresholdNames.clear();
46 m_thresholdTypes.clear();
48
49 for (const TrigConf::Chain& chain : *hltMenu) {
50 try {
51 // For chains with multiple seeds, we cannot determine in this tool which seed passed and which didn't,
52 // so we need to skip these kinds of chains
53 if (chain.l1item().empty() || chain.l1item().find(',')!=std::string::npos) {continue;}
54
55 TrigConf::L1Item item = l1Menu->item(chain.l1item());
56 std::map<std::string,unsigned int> thresholds = logicParser.parse(item.definition())->elementsCount();
57 for (const auto& [thrName, multiplicity] : thresholds) {
58 const TrigConf::L1Threshold& thr = l1Menu->threshold(thrName);
59 // Skip thresholds for which there are no TOBs, e.g. randoms
60 if (vectorContains(m_excludedThresholdTypes.value(), thr.type())) {
61 continue;
62 }
63 TrigCompositeUtils::DecisionID thrNameHash = HLT::Identifier(thr.name());
64 m_thresholdMap[chain.namehash()].insert({thrNameHash, multiplicity});
65 m_monitoredThresholds.insert(thrNameHash);
66 }
67 }
68 catch (const std::exception& ex) {
69 ATH_MSG_ERROR("Exception caught while parsing L1 thresholds for chain " << chain.name() << ": " << ex.what());
70 return StatusCode::FAILURE;
71 }
72 }
73
74 for (const std::shared_ptr<TrigConf::L1Threshold>& thr : l1Menu->thresholds()) {
75 TrigCompositeUtils::DecisionID thrNameHash = HLT::Identifier(thr->name());
76 m_thresholdNames[thrNameHash] = thr->name();
77 m_thresholdTypes[thrNameHash] = thr->type();
78 }
79
80 return StatusCode::SUCCESS;
81}
82
83// =============================================================================
84StatusCode L1DataConsistencyChecker::consistencyCheck(const HLT::IDVec& l1SeededChains, const EventContext& ctx) const {
85 auto monTimer = Monitored::Timer<std::chrono::duration<float, std::milli>>("TIME_consistencyCheck");
86 StatusCode sc = StatusCode::SUCCESS;
87
88 // ---------------------------------------------------------------------------
89 // Get information from TOBs
90 // ---------------------------------------------------------------------------
91 std::ostringstream ssPassedThresholds; // ss for debug printouts, allocate before loop
92 std::unordered_map<TrigCompositeUtils::DecisionID, size_t> tobThresholdCounts; // {thrName hash, nTOBs passing thr}
93 std::unordered_set<std::string> overflowThresholdTypes; // threshold types for which overflow was detected
94 // Loop over threshold types
95 for (const auto& [thrType, decisionsKey] : m_thresholdToDecisionMap.value()) {
96 SG::ReadHandle<TrigCompositeUtils::DecisionContainer> decisions{decisionsKey, ctx.getExtension<Atlas::ExtendedEventContext>().proxy()->name()};
97 if (!decisions.isValid()) {
98 ATH_MSG_DEBUG("No DecisionContainer " << decisionsKey << " for threshold type " << thrType << " found in this event");
99 continue;
100 }
101 size_t idec{0};
102 // Loop over TOBs of the given threshold type (one decision = one TOB)
103 for (const TrigCompositeUtils::Decision* d : *decisions) {
104 std::vector<TrigCompositeUtils::DecisionID> passedThresholdIDs;
105 const bool hasDetail = d->getDetail("thresholds", passedThresholdIDs);
106 if (!hasDetail) {
107 ATH_MSG_ERROR("Detail \"thresholds\" missing from Decision in the container " << decisionsKey);
108 return StatusCode::FAILURE;
109 }
110 bool overflow{false};
111 if (d->hasDetail<char>("overflow")) {
112 overflow = static_cast<bool>(d->getDetail<char>("overflow"));
113 }
114 if (doDebug()) {ssPassedThresholds.str("");}
115 for (const TrigCompositeUtils::DecisionID thrNameHash : passedThresholdIDs) {
116 if (overflow) {
117 overflowThresholdTypes.insert(m_thresholdTypes.at(thrNameHash));
118 }
119 if (tobThresholdCounts.find(thrNameHash)==tobThresholdCounts.end()) {
120 tobThresholdCounts[thrNameHash] = 1;
121 }
122 else {
123 tobThresholdCounts[thrNameHash] += 1;
124 }
125 if (doDebug()) {
126 if (!ssPassedThresholds.str().empty()) ssPassedThresholds << ", ";
127 ssPassedThresholds << m_thresholdNames.at(thrNameHash);
128 }
129 }
130 if (doDebug()) {
131 namespace RoIDefs = HLTSeedingRoIToolDefs;
132 std::optional<RoIDefs::AnyRoIPointer> optTob = RoIDefs::roiFromLink(*d, TrigCompositeUtils::initialRecRoIString());
133 if (optTob.has_value()) {
134 const RoIDefs::AnyRoIPointer& tob = optTob.value();
135 ATH_MSG_DEBUG("Decision " << decisionsKey << "[" << idec << "] corresponds to TOB with word / et / eta / phi = 0x"
136 << MSG::hex << RoIDefs::roiWord(tob) << MSG::dec << " / " << RoIDefs::roiTobEt(tob)
137 << " / " << RoIDefs::roiEta(tob) << " / " << RoIDefs::roiPhi(tob));
138 } else {
139 ATH_MSG_DEBUG("Decision " << decisionsKey << "[" << idec << "] TOB type not supported by template code for "
140 << "debug printout of word / et / eta / phi");
141 }
142 ATH_MSG_DEBUG("Decision " << decisionsKey << "[" << idec << "] TOB passes " << passedThresholdIDs.size()
143 << " thresholds: " << ssPassedThresholds.str());
144 ++idec;
145 }
146 }
147 }
148
149 // ---------------------------------------------------------------------------
150 // Get information from CTP
151 // ---------------------------------------------------------------------------
152 std::unordered_map<TrigCompositeUtils::DecisionID, size_t> ctpThresholdCounts; // {thrName hash, max CTP multiplicity}
153 // Loop over HLT chains activated by CTP
154 for (const TrigCompositeUtils::DecisionID chainID : l1SeededChains) {
155 const auto it = m_thresholdMap.find(chainID);
156 if (it==m_thresholdMap.end()) {
157 ATH_MSG_DEBUG("Cannot monitor chain " << chainID << " -> " << HLT::Identifier(chainID).name() << ", skipping");
158 continue;
159 }
160 const MultiplicityInfo& thresholds = it->second;
161 // Loop over all thresholds required to activate this chain
162 for (const auto& [thrNameHash, multiplicity] : thresholds) {
163 if (ctpThresholdCounts.find(thrNameHash)==ctpThresholdCounts.end()) {
164 ctpThresholdCounts[thrNameHash] = multiplicity;
165 }
166 else if (multiplicity > ctpThresholdCounts[thrNameHash]) {
167 ctpThresholdCounts[thrNameHash] = multiplicity;
168 }
169 }
170 }
171
172 // ---------------------------------------------------------------------------
173 // Perform the consistency check
174 // ---------------------------------------------------------------------------
175 for (const auto& [thrNameHash, ctpCount] : ctpThresholdCounts) {
176 size_t tobCount{0};
177 bool tooFew{false};
178 const auto it = m_thresholdNames.find(thrNameHash);
179 if (it==m_thresholdNames.end()) {
180 ATH_MSG_ERROR("Threshold with hash " << thrNameHash << " not found in the hash->name map");
181 return StatusCode::FAILURE;
182 }
183 const std::string& thrName = it->second;
184 const std::string& thrType = m_thresholdTypes.at(thrNameHash);
185
186 // Check if overflow was detected
187 bool overflow{overflowThresholdTypes.find(thrType)!=overflowThresholdTypes.end()};
188 if (overflow) {
189 ATH_MSG_DEBUG("Threshold " << thrName << " accepted by the CTP with multiplicity " << ctpCount
190 << " is flagged as overflow and thus may be missing TOBs");
191 }
192
193 // True if no TOBs found for this threshold but CTP accepted
194 bool missing = (tobThresholdCounts.find(thrNameHash)==tobThresholdCounts.end());
195
196 if (missing) {
197 if (overflow || !m_errorOnMissingTOB) {
198 ATH_MSG_WARNING("No TOBs found passing the threshold " << thrName
199 << " accepted by the CTP with multiplicity " << ctpCount
200 << (overflow ? ", likely due to overflow" : ""));
201
202 } else {
203 ATH_MSG_ERROR("No TOBs found passing the threshold " << thrName
204 << " accepted by the CTP with multiplicity " << ctpCount);
205 sc = StatusCode::FAILURE;
206 }
207 }
208 else {
209 tobCount = tobThresholdCounts.at(thrNameHash);
210 // True if fewer TOBs found for this threshold than the multiplicity accepted by CTP
211 tooFew = (tobCount < ctpCount);
212 }
213
214 if (tooFew) {
215 if (overflow || !m_errorOnMissingTOB) {
216 ATH_MSG_WARNING("Too few (" << tobCount << ") TOBs found passing the threshold " << thrName
217 << " accepted by the CTP with multiplicity " << ctpCount
218 << (overflow ? ", likely due to overflow" : ""));
219 } else {
220 ATH_MSG_ERROR("Too few (" << tobCount << ") TOBs found passing the threshold " << thrName
221 << " accepted by the CTP with multiplicity " << ctpCount);
222 sc = StatusCode::FAILURE;
223 }
224 }
225
226 if (missing || tooFew) {
227 // Fill the histograms
228 Monitored::Scalar monMissingTOBsIncludingOverflow{"MissingTOBsIncludingOverflow", thrName};
229 if (overflow) {
230 Monitored::Group{m_monTool, monMissingTOBsIncludingOverflow};
231 }
232 else {
233 Monitored::Scalar monMissingTOBs{"MissingTOBs", thrName};
234 Monitored::Group{m_monTool, monMissingTOBs, monMissingTOBsIncludingOverflow};
235 }
236 }
237 else {
238 ATH_MSG_DEBUG("Check passed. Found " << tobCount << " TOBs passing the threshold " << thrName
239 << " accepted by the CTP with multiplicity " << ctpCount);
240 }
241 }
242
243 // Fill extra histograms for debugging
244 for (const TrigCompositeUtils::DecisionID thrNameHash : m_monitoredThresholds) {
245 const auto ctpIt = ctpThresholdCounts.find(thrNameHash);
246 size_t ctpCount = (ctpIt==ctpThresholdCounts.cend()) ? 0 : ctpIt->second;
247 const auto tobIt = tobThresholdCounts.find(thrNameHash);
248 size_t tobCount = (tobIt==tobThresholdCounts.cend()) ? 0 : tobIt->second;
249 int tobMinusCtpCount = static_cast<int>(ctpCount) - static_cast<int>(tobCount); // negative when TOBs are missing
250 const std::string& thrName = m_thresholdNames.at(thrNameHash);
251
252 Monitored::Scalar monThrName{"ThrName", thrName};
253 Monitored::Scalar monCtpCount{"CtpCount", ctpCount};
254 Monitored::Scalar monTobCount{"TobCount", tobCount};
255 Monitored::Scalar monTobMinusCtpCount{"TobMinusCtpCount", tobMinusCtpCount};
256 Monitored::Group{m_monTool, monThrName, monCtpCount, monTobCount, monTobMinusCtpCount};
257 }
258
259 Monitored::Group(m_monTool, monTimer);
260 return sc;
261}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::vector< size_t > vec
static Double_t sc
Header file to be included by clients of the Monitored infrastructure.
Property holding a SG store/key/clid from which a ReadHandle is made.
std::unordered_map< TrigCompositeUtils::DecisionID, MultiplicityInfo > m_thresholdMap
SG::ReadHandleKey< TrigConf::HLTMenu > m_hltMenuKey
Gaudi::Property< std::map< std::string, std::string > > m_thresholdToDecisionMap
std::set< TrigCompositeUtils::DecisionID > m_monitoredThresholds
std::unordered_map< TrigCompositeUtils::DecisionID, std::string > m_thresholdTypes
std::unordered_map< TrigCompositeUtils::DecisionID, unsigned int > MultiplicityInfo
SG::ReadHandleKey< TrigConf::L1Menu > m_l1MenuKey
Gaudi::Property< std::vector< std::string > > m_excludedThresholdTypes
std::unordered_map< TrigCompositeUtils::DecisionID, std::string > m_thresholdNames
virtual StatusCode initialize() override
virtual StatusCode start() override
ToolHandle< GenericMonitoringTool > m_monTool
bool doDebug() const
Shorter alias for a check whether we are in DEBUG logging mode.
Gaudi::Property< bool > m_errorOnMissingTOB
StatusCode consistencyCheck(const HLT::IDVec &l1SeededChains, const EventContext &ctx) const
Perform the check and fill the corresponding histograms.
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
A monitored timer.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
L1 threshold configuration.
Definition L1Item.h:18
Standard L1 threshold configuration.
Collection of template parameter values for the RoIThresholdsTool and RoIsUnpackingToolPhase1 class t...
std::vector< HLT::Identifier > IDVec
unsigned int DecisionID
const std::string & initialRecRoIString()