ATLAS Offline Software
FPGATrackSimEtaPatternFilterTool.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
16 #include "TH2.h"
17 
18 #include <sstream>
19 #include <fstream>
20 #include <cmath>
21 #include <algorithm>
22 #include <iostream>
23 
24 
25 
27 {
28  if (lhs.siTech != rhs.siTech) return lhs.siTech < rhs.siTech;
29  if (lhs.zone != rhs.zone) return lhs.zone < rhs.zone;
30  return lhs.etaModule < rhs.etaModule;
31 }
32 
33 
35 // AthAlgTool
36 
37 FPGATrackSimEtaPatternFilterTool::FPGATrackSimEtaPatternFilterTool(const std::string& algname, const std::string &name, const IInterface *ifc) :
38  base_class(algname, name, ifc)
39 {
40  declareInterface<IFPGATrackSimRoadFilterTool>(this);
41 }
42 
43 
45 {
46  // Retrieve info
47  ATH_CHECK(m_FPGATrackSimMapping.retrieve());
48  ATH_CHECK(m_FPGATrackSimBankSvc.retrieve());
49  m_nLayers = m_FPGATrackSimMapping->PlaneMap_1st()->getNLogiLayers();
50 
51  // Check inputs
52  if (m_pattern_file_path.empty())
53  {
54  ATH_MSG_FATAL("No File Specified");
55  return StatusCode::FAILURE;
56  }
57 
58  // Read pattern file, populate m_patternmap keys
60 
61  // Create inverse map from module to pattern counter, m_moduleHits
62  buildMap();
63 
64  return StatusCode::SUCCESS;
65 }
66 
67 
68 void FPGATrackSimEtaPatternFilterTool::readPatterns(std::string const & filepath)
69 {
70 
71  // Open the file
72  std::ifstream fin(PathResolverFindCalibFile(filepath));
73  if (!fin.is_open())
74  {
75  ATH_MSG_FATAL("Couldn't open " << filepath);
76  throw ("FPGATrackSimEtaPatternFilterTool couldn't open " + filepath);
77  }
78 
79  // Parse the file
80  bool ok = true;
81  std::string line;
82  while (getline(fin, line))
83  {
84  if (line.empty() || line[0] == '#') continue;
85  std::istringstream sline(line);
86 
87  // Read Pattern
89  pattern.resize(m_nLayers);
90  int tech, zone, mod;
91  for (unsigned layer = 0; layer < m_nLayers; layer++)
92  {
93  ok = ok && (sline >> tech >> zone >> mod);
94  if (!ok) break;
95  pattern[layer] = { static_cast<SiliconTech>(tech), static_cast<DetectorZone>(zone), mod };
96  }
97  if (!ok) break;
98 
99  m_patternmap.emplace(pattern, 0);
100  }
101 
102  if (!ok)
103  {
104  ATH_MSG_FATAL("Found error reading file at line: " << line);
105  throw "FPGATrackSimEtaPatternFilterTool read error";
106  }
107 
108  ATH_MSG_INFO("Read " << m_patternmap.size() << " patterns from " << filepath);
109 }
110 
111 
113 {
114  ATH_MSG_DEBUG("Building Map ");
115  m_moduleHits.resize(m_nLayers);
116 
117  for (auto & entry : m_patternmap)
118  {
119  EtaPattern const & patt = entry.first;
120  layer_bitmask_t & counter = entry.second;
121  for (unsigned lyr = 0; lyr < m_nLayers; lyr++)
122  m_moduleHits[lyr][patt[lyr]].addPattern(&counter);
123  }
124 
125  ATH_MSG_DEBUG("Done Building Map ");
126 }
127 
128 
130 {
131  return StatusCode::SUCCESS;
132 }
133 
134 
136 // Main Algorithm
137 
138 StatusCode FPGATrackSimEtaPatternFilterTool::filterRoads(const std::vector<FPGATrackSimRoad*> & prefilter_roads, std::vector<FPGATrackSimRoad*> & postfilter_roads)
139 {
140  m_postfilter_roads.clear();
141  postfilter_roads.clear();
142  for (auto & road : prefilter_roads)
143  {
144  // reset all maps
145  resetCounters();
146 
147 
148  // put hits in module objects
149  addHitsToMap(road);
150 
151  // keep track of used patterns, don't reuse
152  std::set<EtaPattern> usedPatterns;
153 
154  // Count the number of matches from each individual road. This allows a dynamic threshold
155  // during constant generation (where we don't want to discard training tracks).
156  // At least, where we *might* not want to discard training tracks?
157  int numMatches = 0;
158  // check what is above threshold, moving down from 8/8 hits
159  for (unsigned working_threshold = m_nLayers; working_threshold >= m_threshold; working_threshold--)
160  {
161  for (auto & patt_bitmask : m_patternmap)
162  {
163  unsigned nLayers = __builtin_popcount(patt_bitmask.second);
164  if (nLayers >= working_threshold)
165  {
166  // create subpattern from layers that actually have hits
167  EtaPattern subpatt(patt_bitmask.first);
168  for (unsigned lyr = 0; lyr < m_nLayers; lyr++)
169  if (!(patt_bitmask.second & (1 << lyr)))
170  subpatt[lyr] = {}; // defaults to undefined enums = missed
171 
172  // check if this pattern was used already
173  if (usedPatterns.count(subpatt) > 0) continue;
174  addRedundantPatterns(usedPatterns, subpatt, nLayers - m_threshold);
175 
176  // Get an "ID" for the pattern. This is a crude hack but it sort of works
177  // since the keys aren't being changed after the map is created. And provided the
178  // map is created in a consistent order this SHOULD be driven by insertion order.
179  // but this assumption may be fragile.
180  int index = std::distance(m_patternmap.begin(), m_patternmap.find(patt_bitmask.first));
181  if ((uint)index == m_patternmap.size() || index < 0) {
182  ATH_MSG_ERROR("Invalid pattern ID: " << index);
183  }
184  numMatches += 1;
185 
186  // make the road
187  m_postfilter_roads.push_back(buildRoad(patt_bitmask, road, index));
188  }
189  }
190  // If using a "dynamic" threshold-- once matches have been found at a given level, exit.
191  if (numMatches > 0 && m_dynamicThreshold) {
192  break;
193  }
194  }
195  }
196  // copy roads to outputs
197  postfilter_roads.reserve(m_postfilter_roads.size());
199  postfilter_roads.push_back(&r);
200  return StatusCode::SUCCESS;
201 }
202 
204 {
205  for (auto & entry : m_patternmap)
206  entry.second = 0;
207 
208  for (unsigned lyr = 0; lyr < m_nLayers; lyr++)
209  for (auto & entry : m_moduleHits[lyr])
210  entry.second.reset();
211 }
212 
214 {
215  for (unsigned lyr = 0; lyr < m_nLayers; lyr++)
216  for (auto & hit : r->getHits(lyr))
217  if (hit->getHitType() != HitType::wildcard)
218  {
219  ModuleId mod = { hit->getDetType(), hit->getDetectorZone(), (int)(hit->getEtaModule()) };
220  auto itr = m_moduleHits[lyr].find(mod);
221  if (itr != m_moduleHits[lyr].end())
222  itr->second.addHit(hit);
223  else {
224  ATH_MSG_ERROR("Module not in map: " << hit->getDetType() << " " << hit->getDetectorZone() << " " << static_cast<int>(hit->getEtaModule()) );
225  for (auto & itr2 : m_moduleHits[lyr])
226  {
227  ATH_MSG_ERROR(" " << itr2.first.siTech << " " << itr2.first.zone << " " << itr2.first.etaModule);
228  }
229  }
230  }
231 }
232 
233 // Dropping hits from currPattern can still result in valid (duplicated) patterns above threshold.
234 // This functions adds all of those duplicates to a blacklist in "usedPatterns".
235 void FPGATrackSimEtaPatternFilterTool::addRedundantPatterns(std::set<EtaPattern> & usedPatterns, EtaPattern const & currPatt, unsigned nExtra)
236 {
237  usedPatterns.insert(currPatt);
238 
239  std::vector<unsigned> allowmissing(nExtra, 0);
240  bool done = false;
241  while (!done)
242  {
243  EtaPattern subpatt(currPatt);
244  for (auto h : allowmissing)
245  subpatt[h] = {};
246  usedPatterns.insert(subpatt);
247 
248  // increment allowmissing with rollover
249  done = (nExtra == 0);
250  for (unsigned i = 0; i < nExtra; i++)
251  {
252  allowmissing[i]++;
253  if (allowmissing[i] == m_nLayers)
254  {
255  allowmissing[i] = 0;
256  done = (i==nExtra-1); // incremented last counter so were done
257  }
258  else
259  {
260  break;
261  }
262  }
263  }
264 }
265 
266 FPGATrackSimRoad FPGATrackSimEtaPatternFilterTool::buildRoad(std::pair<EtaPattern, layer_bitmask_t> const & patt, FPGATrackSimRoad* origr, int etaPatternID) const
267 {
268  // All roads are now Hough roads.
269  FPGATrackSimRoad r(*origr);
270 
271  r.setHitLayers(patt.second);
272  r.setEtaPatternID(etaPatternID);
273  for (unsigned lyr = 0; lyr < m_nLayers; lyr++) {
274  r.setHits(lyr, m_moduleHits[lyr].find(patt.first[lyr])->second.getHits());
275  if (r.getNHits_layer().at(lyr) == 0) {
276  FPGATrackSimHit *wcHit = new FPGATrackSimHit();
278  wcHit->setDetType(m_FPGATrackSimMapping->PlaneMap_1st()->getDetType(lyr));
279  wcHit->setLayer(lyr);
280  r.setHits(lyr, std::vector<const FPGATrackSimHit*>{wcHit});
281  }
282  }
283 
284  // Here, if told to do so, we'll reset the road's sector using the eta pattern ID.
285  // Perhaps this should also be AND'ed with the "match ideal geometry" setting?
286  // This code is adapted from FPGATrackSimHoughTransformTool::matchIdealGeoSectors, which perhaps
287  // calls for moving this into the road class itself.
288  if (m_doEtaPatternConsts) {
289  int sectorbin = fpgatracksim::ETA_SECTOR_OFFSET*etaPatternID + r.getSectorBin();
290  r.setSectorBin(sectorbin);
291  std::vector<module_t> modules;
292  for (unsigned int il = 0; il < r.getNLayers(); il++) {
293  if (r.getNHits_layer()[il] == 0) {
294  modules.push_back(-1);
295  } else {
296  modules.push_back(sectorbin);
297  }
298  }
299  const FPGATrackSimSectorBank* sectorbank = !m_isSecondStage ? m_FPGATrackSimBankSvc->SectorBank_1st() : m_FPGATrackSimBankSvc->SectorBank_2nd();
300  r.setSector(sectorbank->findSector(modules));
301  }
302  return r;
303 }
304 
305 
307 // Prints
308 
309 std::string FPGATrackSimEtaPatternFilterTool::to_string(const std::vector<unsigned> & v) const
310 {
311  std::ostringstream oss;
312  oss << "[";
313  if (!v.empty())
314  {
315  std::copy(v.begin(), v.end()-1, std::ostream_iterator<unsigned>(oss, ", "));
316  oss << v.back();
317  }
318  oss << "]";
319  return oss.str();
320 }
321 
323 {
324  std::ostringstream oss;
325  oss << "[";
326  for (auto mod : patt) {
327  oss << "[";
328  oss << mod.siTech << ", " << mod.zone << ", " << mod.etaModule;
329  oss << "],";
330  }
331  oss << "]";
332  return oss.str();
333 }
334 
336 {
337  std::ostringstream oss;
338  oss << road.getNHits() << " : [";
339  for (unsigned layer = 0; layer < m_nLayers; layer++) {
340  oss << road.getNHits_layer()[layer] << ",";
341  }
342  oss << "]";
343  return oss.str();
344 }
PlotCalibFromCool.il
il
Definition: PlotCalibFromCool.py:381
mergePhysValFiles.pattern
pattern
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:26
FPGATrackSimEtaPatternFilterTool::ModuleId
Definition: FPGATrackSimEtaPatternFilterTool.h:72
beamspotman.r
def r
Definition: beamspotman.py:676
getMenu.algname
algname
Definition: getMenu.py:53
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
checkFileSG.line
line
Definition: checkFileSG.py:75
fpgatracksim::ETA_SECTOR_OFFSET
constexpr int ETA_SECTOR_OFFSET
Definition: FPGATrackSimConstants.h:25
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
FPGATrackSimPlaneMap.h
Maps physical layers to logical layers.
FPGATrackSimEtaPatternFilterTool::addRedundantPatterns
void addRedundantPatterns(std::set< EtaPattern > &usedPatterns, EtaPattern const &currPatt, unsigned nExtra)
Definition: FPGATrackSimEtaPatternFilterTool.cxx:235
index
Definition: index.py:1
FPGATrackSimEtaPatternFilterTool::ModuleId::siTech
SiliconTech siTech
Definition: FPGATrackSimEtaPatternFilterTool.h:73
FPGATrackSimEtaPatternFilterTool::m_doEtaPatternConsts
Gaudi::Property< bool > m_doEtaPatternConsts
Definition: FPGATrackSimEtaPatternFilterTool.h:65
FPGATrackSimEtaPatternFilterTool::m_isSecondStage
Gaudi::Property< bool > m_isSecondStage
Definition: FPGATrackSimEtaPatternFilterTool.h:64
FPGATrackSimEtaPatternFilterTool::ModuleId::etaModule
int etaModule
Definition: FPGATrackSimEtaPatternFilterTool.h:75
FPGATrackSimEtaPatternFilterTool::m_dynamicThreshold
Gaudi::Property< bool > m_dynamicThreshold
Definition: FPGATrackSimEtaPatternFilterTool.h:66
FPGATrackSimRoad::getNHits_layer
std::vector< size_t > getNHits_layer() const
Definition: FPGATrackSimRoad.cxx:25
FPGATrackSimEtaPatternFilterTool::m_FPGATrackSimBankSvc
ServiceHandle< IFPGATrackSimBankSvc > m_FPGATrackSimBankSvc
Definition: FPGATrackSimEtaPatternFilterTool.h:57
FPGATrackSimEtaPatternFilterTool::to_string
std::string to_string(const EtaPattern &patt) const
Definition: FPGATrackSimEtaPatternFilterTool.cxx:322
FPGATrackSimRoad::getNHits
size_t getNHits() const
Definition: FPGATrackSimRoad.cxx:18
FPGATrackSimConstants.h
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
FPGATrackSimHit
Definition: FPGATrackSimHit.h:38
FPGATrackSimEtaPatternFilterTool::m_postfilter_roads
std::vector< FPGATrackSimRoad > m_postfilter_roads
Definition: FPGATrackSimEtaPatternFilterTool.h:106
HitType::wildcard
@ wildcard
FPGATrackSimEtaPatternFilterTool::resetCounters
void resetCounters()
Definition: FPGATrackSimEtaPatternFilterTool.cxx:203
FPGATrackSimEtaPatternFilterTool::m_FPGATrackSimMapping
ServiceHandle< IFPGATrackSimMappingSvc > m_FPGATrackSimMapping
Definition: FPGATrackSimEtaPatternFilterTool.h:56
FPGATrackSimHit::setDetType
void setDetType(SiliconTech detType)
Definition: FPGATrackSimHit.h:52
FPGATrackSimEtaPatternFilterTool::buildMap
void buildMap()
Definition: FPGATrackSimEtaPatternFilterTool.cxx:112
uint
unsigned int uint
Definition: LArOFPhaseFill.cxx:20
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
maskDeadModules.mod
mod
Definition: maskDeadModules.py:36
FPGATrackSimSectorBank::findSector
sector_t findSector(std::vector< module_t > const &modules) const
Definition: FPGATrackSimSectorBank.cxx:121
SiliconTech
SiliconTech
Definition: FPGATrackSimTypes.h:25
lumiFormat.i
int i
Definition: lumiFormat.py:92
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
extractSporadic.h
list h
Definition: extractSporadic.py:97
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
FPGATrackSimEtaPatternFilterTool::m_moduleHits
std::vector< std::map< ModuleId, ModulesToPattern > > m_moduleHits
Definition: FPGATrackSimEtaPatternFilterTool.h:118
FPGATrackSimEtaPatternFilterTool::addHitsToMap
void addHitsToMap(FPGATrackSimRoad *r)
Definition: FPGATrackSimEtaPatternFilterTool.cxx:213
FPGATrackSimEtaPatternFilterTool::m_threshold
Gaudi::Property< unsigned > m_threshold
Definition: FPGATrackSimEtaPatternFilterTool.h:63
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
FPGATrackSimEtaPatternFilterTool::initialize
virtual StatusCode initialize() override
Definition: FPGATrackSimEtaPatternFilterTool.cxx:44
FPGATrackSimSectorBank
Definition: FPGATrackSimSectorBank.h:30
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
PathResolver.h
python.draw_obj.zone
def zone(nx, ny)
Definition: draw_obj.py:288
FPGATrackSimEtaPatternFilterTool::m_nLayers
unsigned m_nLayers
Definition: FPGATrackSimEtaPatternFilterTool.h:111
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
FPGATrackSimHit.h
: FPGATrackSim-specific class to represent an hit in the detector.
FPGATrackSimEtaPatternFilterTool::filterRoads
virtual StatusCode filterRoads(const std::vector< FPGATrackSimRoad * > &prefilter_roads, std::vector< FPGATrackSimRoad * > &postfilter_roads) override
Definition: FPGATrackSimEtaPatternFilterTool.cxx:138
FPGATrackSimEtaPatternFilterTool::EtaPattern
std::vector< ModuleId > EtaPattern
Definition: FPGATrackSimEtaPatternFilterTool.h:78
FPGATrackSimEtaPatternFilterTool::ModuleId::zone
DetectorZone zone
Definition: FPGATrackSimEtaPatternFilterTool.h:74
FPGATrackSimEtaPatternFilterTool::buildRoad
FPGATrackSimRoad buildRoad(std::pair< EtaPattern, layer_bitmask_t > const &patt, FPGATrackSimRoad *origr, int etaPatternID) const
Definition: FPGATrackSimEtaPatternFilterTool.cxx:266
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
python.PyAthena.v
v
Definition: PyAthena.py:157
FPGATrackSimHit::setLayer
void setLayer(unsigned v)
Definition: FPGATrackSimHit.h:87
DetectorZone
DetectorZone
Definition: FPGATrackSimTypes.h:28
h
FPGATrackSimEtaPatternFilterTool::FPGATrackSimEtaPatternFilterTool
FPGATrackSimEtaPatternFilterTool(const std::string &, const std::string &, const IInterface *)
Definition: FPGATrackSimEtaPatternFilterTool.cxx:37
layer_bitmask_t
uint32_t layer_bitmask_t
Definition: FPGATrackSimTypes.h:22
FPGATrackSimEtaPatternFilterTool::finalize
virtual StatusCode finalize() override
Definition: FPGATrackSimEtaPatternFilterTool.cxx:129
operator<
bool operator<(const FPGATrackSimEtaPatternFilterTool::ModuleId &lhs, const FPGATrackSimEtaPatternFilterTool::ModuleId &rhs)
Definition: FPGATrackSimEtaPatternFilterTool.cxx:26
FPGATrackSimEtaPatternFilterTool.h
Implements road filtering using eta module patterns.
compute_lumi.fin
fin
Definition: compute_lumi.py:19
calibdata.copy
bool copy
Definition: calibdata.py:27
FPGATrackSimEtaPatternFilterTool::readPatterns
void readPatterns(std::string const &filepath)
Definition: FPGATrackSimEtaPatternFilterTool.cxx:68
test_pyathena.counter
counter
Definition: test_pyathena.py:15
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
FPGATrackSimSectorBank.h
This file declares a class that stores the module IDs of the sectors.
FPGATrackSimRoad
Definition: FPGATrackSimRoad.h:29
FPGATrackSimEtaPatternFilterTool::m_patternmap
std::map< EtaPattern, layer_bitmask_t > m_patternmap
Definition: FPGATrackSimEtaPatternFilterTool.h:115
FPGATrackSimHit::setHitType
void setHitType(HitType type)
Definition: FPGATrackSimHit.h:51
FPGATrackSimEtaPatternFilterTool::m_pattern_file_path
Gaudi::Property< std::string > m_pattern_file_path
Definition: FPGATrackSimEtaPatternFilterTool.h:62