ATLAS Offline Software
Loading...
Searching...
No Matches
MuonSectorProcessor.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// First the corresponding header.
8
9// The headers from other ATLAS packages,
10// from most to least dependent.
14#include "TrigConfData/L1Menu.h"
16
17// Headers from external packages.
18#include <boost/property_tree/ptree.hpp>
19#include <boost/property_tree/xml_parser.hpp>
20
21// System headers.
22#include <string>
23#include <sstream>
24#include <iostream>
25#include <map>
26#include <set>
27#include <array>
28#include <vector>
29#include <utility>
30
31using boost::property_tree::ptree;
32
33namespace LVL1MUCTPIPHASE1 {
35
36 std::pair<int,int> barrel_global2local(int sector){
37 auto inoct_sector = ((sector + 2) % 4);
38 auto mioct_number = ((sector + 2) / 4) % 8;
39 return std::make_pair(inoct_sector,mioct_number);
40 }
41
42 int barrel_local2global(int number,int mioct){
43 return ((30 + 4 * mioct) + number) % 32;
44 }
45
46 std::pair<int,int> endcap_global2local(int sector){
47 auto inoct_sector = ((sector + 1) % 6);
48 auto mioct_number = ((sector + 1) / 6) % 8;
49 return std::make_pair(inoct_sector,mioct_number);
50
51 }
52
53 int endcap_local2global(int number,int mioct){
54 return ((47 + 6 * mioct) + number) % 48;
55 }
56 std::pair<int,int> forward_global2local(int sector){
57 auto inoct_sector = (sector % 3);
58 auto mioct_number = (sector / 3) % 8;
59 return std::make_pair(inoct_sector,mioct_number);
60
61 }
62
63 int forward_local2global(int number,int mioct){
64 return ((0 + 3 * mioct) + number) % 24;
65 }
66 };
67
69 {
70 public:
72 std::map<int,std::set<std::string> > global_pairs;
73
74 std::array<std::map<std::string,std::vector<std::string>>,2> lhs_index;
75 std::array<std::map<std::string,std::vector<std::string>>,2> rhs_index;
76
77 std::string make_key(std::string prefix, int global_sec, int roi){
78 prefix += std::to_string(global_sec) + "_" + std::to_string(roi);
79 return prefix;
80 }
81
82 std::string make_pair(const std::string& lhs, const std::string& rhs) const {
83 return lhs + ":" + rhs;
84 }
85
86
88 for(const auto& side_regions : global_pairs ){
89 for(const auto& region : side_regions.second){
90 auto split = region.find(':');
91 auto left = region.substr(0,split);
92 auto right = region.substr(split+1,std::string::npos);
93 lhs_index[side_regions.first][left].push_back(right);
94 rhs_index[side_regions.first][right].push_back(std::move(left));
95 }
96 }
97 }
98
99 std::vector<std::string> get_lhs_keys(const std::string& dettype, int roi, int sector) const {
100 std::vector<std::string> r;
101 r.push_back(dettype + std::to_string(sector) + "_" + std::to_string(roi));
102 return r;
103 }
104
105 std::vector<std::string> get_rhs_keys(const std::string& dettype, int roi, int sector) const {
106 std::vector<std::string> r;
107 r.push_back(dettype + std::to_string(sector) + "_" + std::to_string(roi));
108 return r;
109 }
110
111 std::vector<std::string> relevant_regions(int side, const std::string& dettype, int roi, int sector) const {
112 std::vector<std::string> r;
113 for(const auto& key : get_lhs_keys(dettype,roi,sector)){
114 auto x = lhs_index[side].find(key);
115 if(x != lhs_index[side].end()){
116 for(const auto& rr : x->second){
117 r.push_back(make_pair(key,rr));
118 }
119 }
120 }
121 for(const auto& key : get_rhs_keys(dettype,roi,sector)){
122 auto x = rhs_index[side].find(key);
123 if(x != rhs_index[side].end()){
124 for(const auto& rr : x->second){
125 r.push_back(make_pair(rr,key));
126 }
127 }
128 }
129 return r;
130 }
131
132 void configure(const std::string& lutFile)
133 {
134 ptree inputTree;
135 read_xml(lutFile, inputTree);
136
137 boost::property_tree::ptree topEle = inputTree.get_child("MUCTPI_LUT");
138
139 // iterate through elements of the XML
140 for(const boost::property_tree::ptree::value_type &x: topEle) {
141
142 std::string topElementName = x.first;
143 ptree lut = x.second;
144
145 if (topElementName != "LUT") continue;
146
147 std::string SectorId1 = xmlHelper.getAttribute(lut,"SectorId1");
148 std::string SectorId2 = xmlHelper.getAttribute(lut,"SectorId2");
149
150 unsigned left_mod = 32;
151 unsigned right_mod = 32;
152 if (SectorId1[0] == 'E') left_mod = 48;
153 if (SectorId1[0] == 'F') left_mod = 24;
154 if (SectorId2[0] == 'E') right_mod = 48;
155 if (SectorId2[0] == 'F') right_mod = 24;
156
157 std::string snum_left = std::string(1,SectorId1[1])+std::string(1,SectorId1[2]);
158 int sec_left = std::stoi(snum_left) % left_mod;
159
160 std::string snum_right = std::string(1,SectorId2[1])+std::string(1,SectorId2[2]);
161 int sec_right = std::stoi(snum_right) % right_mod;
162
163 std::string side = xmlHelper.getAttribute(lut,"Side");
164 int active_side = (side == "C") ? 0 : 1;
165
166 std::string System1 = SectorId1.substr(0,1);
167 std::string System2 = SectorId2.substr(0,1);
168
169 for(const boost::property_tree::ptree::value_type &z: lut) {
170 std::string menuElementName = z.first;
171 if(menuElementName!="Element" && menuElementName!="BBElement")continue;
172 ptree ele = z.second;
173 auto roi1 = xmlHelper.getIntAttribute(ele, "RoI1");
174 auto roi2 = xmlHelper.getIntAttribute(ele, "RoI2");
175 auto lhs_key = make_key(System1,sec_left,roi1);
176 auto rhs_key = make_key(System2,sec_right,roi2);
177 auto region = make_pair(lhs_key,rhs_key);
178 global_pairs[active_side].insert(std::move(region));
179 }
180 }
182 }
183 };
184
185
187 :
188 m_overlapHelper(std::make_unique<OverlapHelper>()),
189 m_l1menu(nullptr),
190 m_l1topoLUT(nullptr),
191 m_side(side)
192 {
193 }
194
198
200 : m_overlapHelper(std::move(o.m_overlapHelper)) {}
201
203 {
204 m_l1menu = l1menu;
205 }
206
207 void MuonSectorProcessor::configureOverlapRemoval(const std::string& lutFile)
208 {
209 m_overlapHelper->configure(lutFile);
210 }
211
213 {
214 if (!m_l1menu) return false;
215
216 m_ptEncoding.clear();
217 m_ptEncoding.resize(3);
218
219 //build the map between index and pt threshold.
220 //the index is the 3- or 4-bit pt word, and has a different
221 //pt threshold meaning depending on the subsystem.
222 //the value part of the map is the pt value for the 3 subsystems,
223 //and the key is the index for an arbitrary subsystem.
224 //not all indices will be covered by all subsystems since
225 //barrel only has 3 bits, so initialize the value tuple with -1
226 const auto & exMU = &m_l1menu->thrExtraInfo().MU();
227 auto rpcPtValues = exMU->knownRpcPtValues();
228 auto tgcPtValues = exMU->knownTgcPtValues();
229 for ( unsigned i=0; i<rpcPtValues.size(); i++){
230 m_ptEncoding[0][i] = exMU->ptForRpcIdx(i);
231 }
232 for ( unsigned i=0; i<tgcPtValues.size(); i++){
233 m_ptEncoding[1][i] = exMU->ptForTgcIdx(i);
234 m_ptEncoding[2][i] = exMU->ptForTgcIdx(i);
235 }
236
237 return true;
238 }
239
240
242 {
243 std::map<std::string,std::vector<std::pair<std::shared_ptr<LVL1MUONIF::Lvl1MuSectorLogicDataPhase1>, unsigned> > > buckets;
244
245 for (size_t isys=0;isys<LVL1MUONIF::Lvl1MuCTPIInputPhase1::numberOfSystems();isys++)
246 {
247 // Sectors per system
249 for (size_t isec=0;isec<LVL1MUONIF::Lvl1MuCTPIInputPhase1::numberOfSector(system);isec++)
250 {
251 // A+C sides
252 for (size_t isub=0;isub<2;isub++)
253 {
254 if (isub != size_t(m_side)) continue;
255
256 //get a pointer to this since we'll need to modify the 'veto' flag of the SL data
257 std::shared_ptr<LVL1MUONIF::Lvl1MuSectorLogicDataPhase1> sectorData = inputs->getSectorLogicDataPtr(isys, isub, isec, bcid);
258 if (!sectorData) continue;
259
260 for (unsigned int icand=0;icand<LVL1MUONIF::NCAND[isys];icand++)
261 {
262 //build the sector name
263 std::string sectorName="";
264 if (isys == 0) sectorName="B";
265 else if (isys == 1) sectorName="E";
266 else if (isys == 2) sectorName="F";
267
268 int roiID = sectorData->roi(icand);
269 if (roiID < 0) continue;
270 int ptword = sectorData->pt(icand);
271 if (ptword < 0) continue;
272
273 // initializing veto flag for the latter removal step
274 sectorData->veto(icand,0);
275
276 for(auto rr : m_overlapHelper->relevant_regions(m_side,sectorName,roiID,isec))
277 {
278 // for the barrel-barrel overlap removal, only the muons having the phi-overlap flag are considered
279 if( std::count(rr.begin(),rr.end(),'B') == 2 && isys == 0 && sectorData->ovl(icand) == 0 )continue;
280 buckets[rr].push_back(std::make_pair(sectorData, icand));
281 }
282 }
283 }
284 }
285 }
286
287 for(auto candidate_vector : buckets){ // loop over candidates in OL region pair
288
289 // sorting (to be tuned)
290 unsigned i_notRemove = 0;
291 int ptMax = 0;
292 for (unsigned i=0;i<candidate_vector.second.size();i++){
293 if( candidate_vector.second[i].first->veto(candidate_vector.second[i].second)==1 ) continue; // skipping already-flagged candidate
294 int pt = candidate_vector.second[i].first->pt(candidate_vector.second[i].second);
295 if(pt > ptMax){
296 ptMax = pt;
297 i_notRemove = i;
298 }
299 }
300
301 //for each candidate except the highest pt, mark them for removal
302 for (unsigned i=0;i<candidate_vector.second.size();i++)
303 {
304 if( candidate_vector.second[i].first->veto(candidate_vector.second[i].second)==1 ) continue; // skipping already-flagged candidate
305 candidate_vector.second[i].first->veto(candidate_vector.second[i].second, (i==i_notRemove)?0:1 );
306 }
307 }
308 }
309
311 LVL1::MuCTPIL1Topo& l1topoData) const
312 {
313 // Barrel + EC + Fwd
314 for (unsigned short isys=0;isys<LVL1MUONIF::Lvl1MuCTPIInputPhase1::numberOfSystems();isys++)
315 {
316 // Sectors per system
318 for (unsigned short isec=0;isec<LVL1MUONIF::Lvl1MuCTPIInputPhase1::numberOfSector(system);isec++)
319 {
320 // A+C sides
321 for (unsigned short isub=0;isub<2;isub++)
322 {
323 if (isub != (unsigned short)(m_side)) continue;
324 std::shared_ptr<LVL1MUONIF::Lvl1MuSectorLogicDataPhase1> sectorData = inputs->getSectorLogicDataPtr(isys, isub, isec, bcid);
325 if (!sectorData) continue;
326
327 //build the sector name
328 std::stringstream sectorName;
329 if (isys == 0) sectorName<<"B";
330 else if (isys == 1) sectorName<<"E";
331 else if (isys == 2) sectorName<<"F";
332
334 if (isys == 0)
335 {
336 int sectorNumber=isec;
337 if (side == LVL1MUONIF::Lvl1MuCTPIInputPhase1::idSideC()) sectorNumber += 32;
338 if (sectorNumber < 10) sectorName << "0";
339 sectorName << sectorNumber;
340 }
341 else
342 {
343 if (side == LVL1MUONIF::Lvl1MuCTPIInputPhase1::idSideA()) sectorName << "A";
344 else sectorName << "C";
345 if (isec < 10) sectorName << "0";
346 sectorName << isec;
347 }
348
349
350 for (unsigned int icand=0;icand<LVL1MUONIF::NCAND[isys];icand++)
351 {
352 //find the eta/phi
353 int roiID = sectorData->roi(icand);
354 if (roiID < 0) continue;
355 int ptword = sectorData->pt(icand);
356 if (ptword < 0) continue;
357
358 // the following doesn't quite follow the correct nomenclature, should be (side, isub, isec, roiID) thus there was a typo chain in L399+ using isub instead of the correct isys
359 // see: https://gitlab.cern.ch/atlas/athena/-/blob/master/Trigger/TrigT1/TrigT1MuctpiPhase1/src/L1TopoLUT.cxx#L161
360 L1TopoCoordinates coord = m_l1topoLUT->getCoordinates(isub, isys, isec, roiID);
361
362 //check for invalid decoding
363 if (coord == L1TopoCoordinates())
364 {
365 std::stringstream err;
366 err << "Couldn't decode L1Topo coordinates: Side = " << isub << ", subsystem = " << isys << ", sector = " << isec << ", roi = " << roiID;
367 return err.str();
368 }
369
370 int ptValue = 0;
371 auto enc = m_ptEncoding[isys].find(ptword);
372 if (enc == m_ptEncoding[isys].end())
373 {
374 auto last_enc = m_ptEncoding[isys].rbegin();
375 if (last_enc != m_ptEncoding[isys].rend() && ptword > last_enc->first)
376 {
377 ptValue = m_ptEncoding[isys].rbegin()->second;
378 }
379 else
380 {
381 std::stringstream err;
382 err << "Pt threshold not found in L1Topo encoding. Thr: " << ptword << ", subsys: " << isys;
383 return err.str();
384 }
385 }
386 else ptValue=enc->second;
387
388 if (ptValue < 0)
389 {
390 std::stringstream err;
391 err << "Default value returned for pt encoding. Thr: " << ptword << ", isys: " << isys;
392 return err.str();
393 }
394
395
396 // no longer needed, but keep for backwards compatibility
397 int etacode=0;
398 int phicode = 0;
399 unsigned int mioctID = 0;
400 unsigned int ptCode=0;
401
403 cand.setCandidateData(sectorName.str(),
404 roiID,
405 bcid,
406 (unsigned int)ptword,
407 ptCode, //removed Run3
408 (unsigned int)ptValue,
409 coord.eta,
410 coord.phi,
411 etacode, //removed Run3
412 phicode, //removed Run3
413 coord.eta_min,
414 coord.eta_max,
415 coord.phi_min,
416 coord.phi_max,
417 mioctID, //removed Run3
418 coord.ieta,
419 coord.iphi);
420
421 if (isys == 0) cand.setRPCFlags(sectorData->is2candidates(icand),
422 sectorData->ovl(icand));
423 else cand.setTGCFlags(sectorData->bw2or3(icand),
424 sectorData->innercoin(icand),
425 sectorData->goodmf(icand),
426 sectorData->charge(icand));
427
428
429 l1topoData.addCandidate(cand);
430 }
431 }
432 }
433 }
434 return "";
435 }
436
437}
const boost::regex rr(r_r)
double coord
Type of coordination system.
boost::property_tree::ptree ptree
#define x
#define z
std::vector< std::map< int, int > > m_ptEncoding
void setMenu(const TrigConf::L1Menu *l1menu)
void runOverlapRemoval(LVL1MUONIF::Lvl1MuCTPIInputPhase1 *inputs, int bcid) const
std::string makeL1TopoData(LVL1MUONIF::Lvl1MuCTPIInputPhase1 *inputs, int bcid, LVL1::MuCTPIL1Topo &l1topoData) const
std::unique_ptr< OverlapHelper > m_overlapHelper
void configureOverlapRemoval(const std::string &lutFile)
std::vector< std::string > get_rhs_keys(const std::string &dettype, int roi, int sector) const
std::array< std::map< std::string, std::vector< std::string > >, 2 > rhs_index
std::array< std::map< std::string, std::vector< std::string > >, 2 > lhs_index
void configure(const std::string &lutFile)
std::string make_key(std::string prefix, int global_sec, int roi)
std::vector< std::string > relevant_regions(int side, const std::string &dettype, int roi, int sector) const
std::map< int, std::set< std::string > > global_pairs
std::string make_pair(const std::string &lhs, const std::string &rhs) const
std::vector< std::string > get_lhs_keys(const std::string &dettype, int roi, int sector) const
Class representing (part of) the input data to the MuCTPI for Phase 1.
static size_t numberOfSector(MuonSystem system)
MuCTPI input class to the L1Topo simulation.
void setRPCFlags(bool is2cand, bool phiOvl)
void setTGCFlags(bool bw2or3, bool innerCoin, bool goodMF, int charge)
void setCandidateData(const std::string &sectorName, unsigned int roiID, unsigned int bcid, unsigned int ptThresholdID, unsigned int ptL1TopoCode, unsigned int ptValue, float eta, float phi, unsigned int etacode, unsigned int phicode, float etamin, float etamax, float phimin, float phimax, unsigned int mioctID, int ieta, int iphi)
MuCTPI input class to the L1Topo simulation.
void addCandidate(const MuCTPIL1TopoCandidate &candidate)
L1 menu configuration.
Definition L1Menu.h:28
int r
Definition globals.cxx:22
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
static const size_t NCAND[3]
STL namespace.
std::pair< int, int > barrel_global2local(int sector)
std::pair< int, int > endcap_global2local(int sector)
std::pair< int, int > forward_global2local(int sector)
int forward_local2global(int number, int mioct)
std::string number(const double &d, const std::string &s)
Definition utils.cxx:186