ATLAS Offline Software
Loading...
Searching...
No Matches
TrigThresholdDecisionTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
7
8namespace LVL1
9{
11 const char ContainerName[] = "LVL1MuonRoIs";
12 const char ThresholdType[] = "MU";
13 }
14
16 const std::string& name,
17 const IInterface* parent)
18 : base_class(type, name, parent) {}
19
21 {
22 ATH_MSG_DEBUG( "========================================" );
23 ATH_MSG_DEBUG( "Initialize for TrigThresholdDecisionTool" );
24 ATH_MSG_DEBUG( "========================================" );
25
27 ATH_CHECK( m_rpcTool.retrieve() );
28 ATH_CHECK( m_tgcTool.retrieve() );
29
30 if(m_MenuFromxAOD) {
31 ATH_CHECK( m_configSvc.retrieve() );
32 }
33 return StatusCode::SUCCESS;
34 }
35
37 {
38 ATH_MSG_DEBUG( "==========================================" );
39 ATH_MSG_DEBUG( "Start for Phase1 TrigThresholdDecisionTool" );
40 ATH_MSG_DEBUG( "==========================================" );
41
42 // we configure the tool here only if we are not running from xAOD
43 if (!m_MenuFromxAOD){
44
46 ATH_CHECK(l1Menu.isValid());
48 }
49 return StatusCode::SUCCESS;
50 }
51
53
54 std::lock_guard guard{m_mutex};
55 if (m_isInitialized) {
56 return StatusCode::SUCCESS;
57 }
58
59 m_parsed_flags.clear();
60 m_tgcFlag_decisions.clear();
61 m_rpcFlag_decisions.clear();
62
63 //front-load the TGC flag parsing and all possible 3-bit decisions for the menu
64 std::optional<ThrVecRef> menuThresholds = getMenuThresholds(l1Menu);
65 ATH_CHECK(menuThresholds.has_value());
66
67 for (const std::shared_ptr<TrigConf::L1Threshold>& thrBase : menuThresholds.value().get()) {
68 auto thr = static_cast<TrigConf::L1Threshold_MU*>(thrBase.get());
69
70 //parse the tgc flags and buffer them
71 std::string tgcFlags = getShapedFlags( thr->tgcFlags() );
72 parseFlags(tgcFlags);
73
74 //loop over all 3-bit flag combinations
75 for (unsigned flags=0;flags<8;flags++) {
76 bool F=flags&0b100;
77 bool C=flags&0b010;
78 bool H=flags&0b001;
79 makeTGCDecision(tgcFlags, F, C, H);
80 }
81
82 //parse the rpc flags and buffer them
83 std::string rpcFlags = getShapedFlags( thr->rpcFlags() );
84 parseFlags(rpcFlags);
85
86 //loop over all 2-bit flag combinations
87 for (unsigned flags=0;flags<2;flags++){
88 bool M=flags&0b1;
89 makeRPCDecision(rpcFlags, M);
90 }
91 }
92 m_isInitialized = true;
93 return StatusCode::SUCCESS;
94}
95
96 uint64_t TrigThresholdDecisionTool::getPattern(const EventContext& /*ctx*/,
97 const xAOD::MuonRoI& roi,
98 const ThrVec& menuThresholds,
99 const TrigConf::L1ThrExtraInfoBase& menuExtraInfo) const {
100 return getPattern(roi.roiWord(), menuThresholds, menuExtraInfo);
101 }
102
103 uint64_t TrigThresholdDecisionTool::getPattern(uint32_t dataWord,
104 const ThrVec& menuThresholds,
105 const TrigConf::L1ThrExtraInfoBase& menuExtraInfo) const {
106 if (m_MenuFromxAOD and !m_isInitialized){
107 const TrigConf::L1Menu& l1Menu = m_configSvc->l1Menu( Gaudi::Hive::currentContext());
108 if (configureToolFromMenu(l1Menu) != StatusCode::SUCCESS){
109 throw std::runtime_error("Error configuring the TrigThresholdDecisionTool from metadata!");
110 }
111 }
112
113 uint64_t thresholdsPattern = 0;
114
115 //first figure out if we need to use the RPC or TGC tool for decoding the ROI
116 LVL1::ITrigT1MuonRecRoiTool::MuonTriggerSystem system = m_rpcTool->getSystem(dataWord);
117 const LVL1::ITrigT1MuonRecRoiTool* roiTool;
118 if (system == LVL1::ITrigT1MuonRecRoiTool::Barrel) roiTool = &(*m_rpcTool);
119 else roiTool = &(*m_tgcTool);
120
121 //buffer the some information
122 unsigned isub = roiTool->getBitMaskValue(&dataWord, roiTool->SubSysIDMask());
124 unsigned ptword = roiTool->getBitMaskValue(&dataWord, roiTool->ThresholdMask());
125 unsigned roi, sectorID;
127 roi = roiTool->getBitMaskValue(&dataWord, roiTool->BarrelRoIMask());
128 sectorID = roiTool->getBitMaskValue(&dataWord, roiTool->BarrelSectorIDMask());
129 } else if (system == LVL1::ITrigT1MuonRecRoiTool::Endcap) {
130 roi = roiTool->getBitMaskValue(&dataWord, roiTool->EndcapRoIMask());
131 sectorID = roiTool->getBitMaskValue(&dataWord, roiTool->EndcapSectorIDMask());
132 } else { // Forward
133 roi = roiTool->getBitMaskValue(&dataWord, roiTool->ForwardRoIMask());
134 sectorID = roiTool->getBitMaskValue(&dataWord, roiTool->ForwardSectorIDMask());
135 }
136 const TrigConf::L1ThrExtraInfo_MU& muThrExtraInfo = dynamic_cast<const TrigConf::L1ThrExtraInfo_MU&>(menuExtraInfo);
137
138 //buffer (notional) TGC/RPC flags
139 bool F=false, C=false, H=false, M=false;
141 {
142 M = dataWord & roiTool->OverflowPerRoIMask();
143 }
144 else
145 {
146 F = dataWord & roiTool->BW2Or3Mask();
147 C = dataWord & roiTool->InnerCoinMask();
148 H = dataWord & roiTool->GoodMFMask();
149 }
150
151 //loop over the thresholds
152 for (const std::shared_ptr<TrigConf::L1Threshold>& thrBase : menuThresholds) {
153 auto thr = static_cast<TrigConf::L1Threshold_MU*>(thrBase.get());
154
155 bool passed{false};
157 //skip the threshold with regions not corresponding to ALL or barrel
158 if (thr->region().find("ALL") == std::string::npos &&
159 thr->region().find("BA") == std::string::npos) continue;
160
161 //veto this candidate from this multiplicity if it's part of the excluded ROI list
162 const bool isSideC = (side == LVL1MUONIF::Lvl1MuCTPIInputPhase1::idSideC());
163 if (isExcludedRPCROI(muThrExtraInfo, thr->rpcExclROIList(), roi, sectorID, isSideC)) continue;
164
165 if (ptword >= thr->idxBarrel()) {
166 // mark this threshold as passed
167 passed = true;
168 }
169
170 passed &= getRPCDecision(getShapedFlags(thr->rpcFlags()), M);
171 }
172 else { // Endcap or Forward
173 if (system == LVL1MUONIF::Lvl1MuCTPIInputPhase1::idEndcapSystem()) { // Endcap
174 //skip the threshold with regions not corresponding to ALL or endcap
175 if (thr->region().find("ALL") == std::string::npos &&
176 thr->region().find("EC") == std::string::npos) continue;
177
178 if (ptword >= thr->idxEndcap()) {
179 // mark this threshold as passed
180 passed = true;
181 }
182 }
183 else { // Forward
184 //skip the threshold with regions not corresponding to ALL or forward
185 if (thr->region().find("ALL") == std::string::npos &&
186 thr->region().find("FW") == std::string::npos) continue;
187
188 if (ptword >= thr->idxForward()) {
189 // mark this threshold as passed
190 passed = true;
191 }
192 }
193
194 passed &= getTGCDecision(getShapedFlags(thr->tgcFlags()), F, C, H);
195 } // end Endcap or Forward
196
197 if (passed) {
198 // set the corresponding bit in the pattern
199 thresholdsPattern |= (1ull << thr->mapping());
200 }
201
202 } // loop over thresholds
203
204 return thresholdsPattern;
205 }
206
207 std::vector<std::pair<std::shared_ptr<TrigConf::L1Threshold>, bool> >
209 const EventContext& eventContext) const {
210 // Retrieve the L1 menu configuration
211 const TrigConf::L1Menu* l1Menu;
212 if (m_MenuFromxAOD){
213 l1Menu = &m_configSvc->l1Menu( eventContext );
214 if (!m_isInitialized){
215 if (configureToolFromMenu(*l1Menu) != StatusCode::SUCCESS){
216 throw std::runtime_error("Error configuring the TrigThresholdDecisionTool from metadata!");
217 }
218 }
219 }
220 else{
221 SG::ReadHandle<TrigConf::L1Menu> l1MenuHandle = SG::makeHandle(m_l1MenuKey, eventContext);
222 l1Menu = l1MenuHandle.cptr();
223 }
224
225 std::optional<ThrVecRef> menuThresholds = getMenuThresholds(*l1Menu);
226 std::optional<ExtraInfoRef> menuExtraInfo = getMenuThresholdExtraInfo(*l1Menu);
227 // Call the other overload
228 return getThresholdDecisions(dataWord, menuThresholds.value().get(), menuExtraInfo.value().get());
229 }
230
231 std::vector<std::pair<std::shared_ptr<TrigConf::L1Threshold>, bool> >
233 const ThrVec& menuThresholds,
234 const TrigConf::L1ThrExtraInfoBase& menuExtraInfo) const {
235 if (m_MenuFromxAOD and !m_isInitialized){
236 const TrigConf::L1Menu& l1Menu = m_configSvc->l1Menu( Gaudi::Hive::currentContext());
237 if (configureToolFromMenu(l1Menu) != StatusCode::SUCCESS){
238 throw std::runtime_error("Error configuring the TrigThresholdDecisionTool from metadata!");
239 }
240 }
241
242 const uint64_t pattern = getPattern(dataWord, menuThresholds, menuExtraInfo);
243
244 //the object that will be returned: pairs of thresholds and pass/fail decisions
245 std::vector<std::pair<std::shared_ptr<TrigConf::L1Threshold>, bool> > threshold_decisions;
246 threshold_decisions.resize(menuThresholds.size());
247 for (const std::shared_ptr<TrigConf::L1Threshold>& thr : menuThresholds) {
248 const bool decision = pattern & (1 << thr->mapping());
249 threshold_decisions[thr->mapping()] = std::make_pair(thr, decision);
250 }
251 return threshold_decisions;
252 }
253
254 std::pair<std::string, double> TrigThresholdDecisionTool::getMinThresholdNameAndValue(const std::vector<std::pair<std::shared_ptr<TrigConf::L1Threshold>, bool> >& decisions, const double& eta) const
255 {
256 if (m_MenuFromxAOD and !m_isInitialized){
257 const TrigConf::L1Menu& l1Menu = m_configSvc->l1Menu( Gaudi::Hive::currentContext());
258 if (configureToolFromMenu(l1Menu) != StatusCode::SUCCESS){
259 throw std::runtime_error("Error configuring the TrigThresholdDecisionTool from metadata!");
260 }
261 }
262
263 //find the highest pt threshold passed - depite the name of this function
264 std::string thrName="";
265 double thrVal=0;
266 double thrValTmp=0;
267 for (unsigned idec=0;idec<decisions.size();++idec) {
268 if (!decisions[idec].second) continue;
269 std::shared_ptr<TrigConf::L1Threshold_MU> thr = std::static_pointer_cast<TrigConf::L1Threshold_MU>(decisions[idec].first);
270 if(std::abs(eta)<1.05){
271 thrValTmp = thr->ptBarrel();
272 }
273 else{
274 thrValTmp = thr->ptEndcap();
275 }
276 if (thrValTmp > thrVal)
277 {
278 thrVal = thrValTmp;
279 thrName = thr->name();
280 }
281 }
282 return std::make_pair(thrName, thrVal);
283 }
284
286 const std::string& rpcExclROIList,
287 const unsigned roi,
288 const unsigned sectorID,
289 const bool isSideC) const {
290 if (rpcExclROIList != "")
291 {
292 const std::map<std::string, std::vector<unsigned int> >& exclList = menuExtraInfo.exclusionList(rpcExclROIList);
293 if (exclList.size() != 0)
294 {
295 //build the sector name of this ROI to compare against the exclusion list
296 std::stringstream sectorName;
297 sectorName<<"B";
298 int sectorNumber=sectorID;
299 if (isSideC) sectorNumber += 32;
300 if (sectorNumber < 10) sectorName << "0";
301 sectorName << sectorNumber;
302
303 //do the comparison
304 auto exclROIs = exclList.find(sectorName.str());
305 if (exclROIs != exclList.end())
306 {
307 for (auto roi_itr=exclROIs->second.begin();roi_itr!=exclROIs->second.end();roi_itr++)
308 {
309 if (*roi_itr == roi) return true;
310 }
311 }
312 }
313 } // rpcExclList != ""
314
315 return false;
316 }
317
318 bool TrigThresholdDecisionTool::getTGCDecision(const std::string& tgcFlags, const bool F, const bool C, const bool H) const
319 {
320 //check if the word has been checked before for this string of flags (it should always, as we've buffered them in 'start')
321 TGCFlagDecision decision(F,C,H);
322 auto previous_decisions = m_tgcFlag_decisions.find(tgcFlags);
323 if (previous_decisions == m_tgcFlag_decisions.end()) return false;
324
325 auto previous_decision_itr = previous_decisions->second.find(decision);
326 if (previous_decision_itr != previous_decisions->second.end()) return previous_decision_itr->pass;
327 return false;
328 }
329
330 void TrigThresholdDecisionTool::makeTGCDecision(const std::string& tgcFlags, const bool F, const bool C, const bool H) const
331 {
332 //check if the word has been checked before for this string of flags
333 TGCFlagDecision decision(F,C,H);
334 auto previous_decisions = &m_tgcFlag_decisions[tgcFlags];
335 auto previous_decision_itr = previous_decisions->find(decision);
336 if (previous_decision_itr != previous_decisions->end()) return;
337 else if (tgcFlags == "") {
338 decision.pass=true;
339 previous_decisions->insert(decision);
340 }
341 else { // make the decision
342
343 //check the quality based on the flags.
344 //loop over outer layer of "ors" and 'or' the results
345 bool passedFlags = false;
346 const std::vector<std::vector<std::string> >* vec_flags = &m_parsed_flags[tgcFlags];
347 for (auto or_itr = vec_flags->begin();or_itr!=vec_flags->end();or_itr++)
348 {
349 //loop over the inner layer of "ands" and 'and' the results
350 bool passedAnd = true;
351 for (auto and_itr = or_itr->begin();and_itr!=or_itr->end();and_itr++)
352 {
353 if (*and_itr == "F") passedAnd = passedAnd && F;
354 else if (*and_itr == "C") passedAnd = passedAnd && C;
355 else if (*and_itr == "H") passedAnd = passedAnd && H;
356 }
357 passedFlags = passedFlags || passedAnd;
358 }
359 //buffer the decision
360 decision.pass = passedFlags;
361 previous_decisions->insert(decision);
362 }
363 }
364
365 bool TrigThresholdDecisionTool::getRPCDecision(const std::string& rpcFlags, const bool M) const
366 {
367 //check if the word has been checked before for this string of flags (it should always, as we've buffered them in 'start')
368 RPCFlagDecision decision(M);
369 auto previous_decisions = m_rpcFlag_decisions.find(rpcFlags);
370 if (previous_decisions == m_rpcFlag_decisions.end()) return false;
371
372 auto previous_decision_itr = previous_decisions->second.find(decision);
373 if (previous_decision_itr != previous_decisions->second.end()) return previous_decision_itr->pass;
374 return false;
375 }
376
377 void TrigThresholdDecisionTool::makeRPCDecision(const std::string& rpcFlags, const bool M) const
378 {
379 //check if the word has been checked before for this string of flags
380 RPCFlagDecision decision(M);
381 auto previous_decisions = &m_rpcFlag_decisions[rpcFlags];
382 auto previous_decision_itr = previous_decisions->find(decision);
383 if (previous_decision_itr != previous_decisions->end()) return;
384 else if (rpcFlags == "") {
385 decision.pass=true;
386 previous_decisions->insert(decision);
387 }
388 else { // make the decision
389
390 //check the quality based on the flags.
391 //loop over outer layer of "ors" and 'or' the results
392 bool passedFlags = false;
393 const std::vector<std::vector<std::string> >* vec_flags = &m_parsed_flags[rpcFlags];
394 for (auto or_itr = vec_flags->begin();or_itr!=vec_flags->end();or_itr++)
395 {
396 //loop over the inner layer of "ands" and 'and' the results
397 bool passedAnd = true;
398 for (auto and_itr = or_itr->begin();and_itr!=or_itr->end();and_itr++)
399 {
400 if (*and_itr == "M") passedAnd = passedAnd && M;
401 }
402 passedFlags = passedFlags || passedAnd;
403 }
404 //buffer the decision
405 decision.pass = passedFlags;
406 previous_decisions->insert(decision);
407 }
408 }
409
410 void TrigThresholdDecisionTool::parseFlags(const std::string& flags) const
411 {
412 //parse the logic of the quality flag into a 2D vector, where outer layer contains the logic |'s and inner layer contains the logical &'s.
413 //save the 2D vector in a map so we don't have to parse it each time we want to check the flags.
414 if (m_parsed_flags.find(flags) == m_parsed_flags.end())
415 {
416 std::vector<std::string> vec_ors = parseString(flags, "|");
417 std::vector<std::vector<std::string> > vec_flags;
418 for (unsigned ior=0;ior<vec_ors.size();ior++)
419 {
420 vec_flags.push_back(parseString(vec_ors[ior],"&"));
421 }
422 m_parsed_flags[flags] = std::move(vec_flags);
423 }
424 }
425
426 std::vector<std::string> TrigThresholdDecisionTool::parseString(const std::string& str, const std::string& sep) const
427 {
428 std::vector<std::string> parsed;
429 int pos = 0;
430 bool first = true;
431 if (str.size() == 0) return parsed;
432 if (str.find(sep) == std::string::npos)
433 {
434 parsed.push_back(str);
435 return parsed;
436 }
437 while (true)
438 {
439 int newPos = str.find(sep, pos);
440 if (str.find(sep, pos) == std::string::npos)
441 {
442 if (!first) parsed.push_back(str.substr(pos, newPos-pos));
443 break;
444 }
445 std::string sub = str.substr(pos, newPos-pos);
446 parsed.push_back(std::move(sub));
447 pos = newPos+1;
448 first = false;
449 }
450 return parsed;
451 }
452 std::string TrigThresholdDecisionTool::getShapedFlags(const std::string& flags) const
453 {
454 std::string shapedFlags = flags;
455 shapedFlags.erase(std::remove_if(shapedFlags.begin(),shapedFlags.end(),::isspace),shapedFlags.end()); // remove spaces
456 std::vector<std::string> vec_ors = parseString(shapedFlags,"|");
457 std::set<std::string> set_ors;
458 for(const auto& ors : vec_ors){
459 std::vector<std::string> vec_ands = parseString(ors,"&");
460 std::set<std::string> set_ands;
461 for(const auto& ands : vec_ands){
462 set_ands.insert(ands);
463 }
464 std::string aa = "";
465 for(const auto& ands : set_ands){
466 aa += ands;
467 aa += "&";
468 }
469 std::string bb = aa.substr(0,aa.size()-1); // remove the last "&"
470 set_ors.insert(std::move(bb));
471 }
472 std::string aa = "";
473 for(const auto& ors : set_ors){
474 aa += ors;
475 aa += "|";
476 }
477 std::string bb = aa.substr(0,aa.size()-1); // remove the last "|"
478 return bb;
479 }
480}
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x)
bool passed(DecisionID id, const DecisionIDContainer &)
checks if required decision ID is in the set of IDs in the container
#define F(x, y, z)
Definition MD5.cxx:112
#define H(x, y, z)
Definition MD5.cxx:114
unsigned int ForwardSectorIDMask() const
unsigned int OverflowPerRoIMask() const
unsigned int BarrelSectorIDMask() const
unsigned int ForwardRoIMask() const
unsigned int getBitMaskValue(const unsigned int *uintValue, const unsigned int mask) const
unsigned int EndcapSectorIDMask() const
bool getTGCDecision(const std::string &tgcFlags, bool F, bool C, bool H) const
ToolHandle< LVL1::ITrigT1MuonRecRoiTool > m_tgcTool
std::string getShapedFlags(const std::string &flags) const
virtual uint64_t getPattern(const EventContext &ctx, const xAOD::MuonRoI &roi, const ThrVec &menuThresholds, const TrigConf::L1ThrExtraInfoBase &menuExtraInfo) const override
bool isExcludedRPCROI(const TrigConf::L1ThrExtraInfo_MU &menuExtraInfo, const std::string &rpcExclROIList, unsigned roi, unsigned sectorID, bool isSideC) const
virtual std::vector< std::pair< std::shared_ptr< TrigConf::L1Threshold >, bool > > getThresholdDecisions(uint32_t dataWord, const EventContext &eventContext) const override
void makeTGCDecision(const std::string &tgcFlags, bool F, bool C, bool H) const
ServiceHandle< TrigConf::ITrigConfigSvc > m_configSvc
virtual std::pair< std::string, double > getMinThresholdNameAndValue(const std::vector< std::pair< std::shared_ptr< TrigConf::L1Threshold >, bool > > &decisions, const double &eta=0) const override
StatusCode configureToolFromMenu(const TrigConf::L1Menu &l1Menu) const
ToolHandle< LVL1::ITrigT1MuonRecRoiTool > m_rpcTool
void makeRPCDecision(const std::string &rpcFlags, bool M) const
std::vector< std::string > parseString(const std::string &str, const std::string &sep) const
void parseFlags(const std::string &flags) const
virtual StatusCode initialize() override
TrigThresholdDecisionTool(const std::string &type, const std::string &name, const IInterface *parent)
bool getRPCDecision(const std::string &rpcFlags, bool M) const
virtual StatusCode initialize() override
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
L1 menu configuration.
Definition L1Menu.h:28
L1 extra information for certain threshold types.
const std::map< std::string, std::vector< unsigned int > > & exclusionList(const std::string &listName) const
uint32_t roiWord() const
The "raw" RoI word describing the muon candidate.
struct color C
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
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.
MuonRoI_v1 MuonRoI
Definition MuonRoI.h:15