ATLAS Offline Software
FPGATrackSimOverlapRemovalTool.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 #include "../FPGATrackSimAlgorithms/FPGATrackSimOverlapRemovalTool.h"
6 
7 #include "GaudiKernel/MsgStream.h"
8 
9 #include <sstream>
10 #include <iostream>
11 #include <fstream>
12 
14 FPGATrackSimOverlapRemovalTool::FPGATrackSimOverlapRemovalTool(const std::string& algname, const std::string& name, const IInterface *ifc) :
15  AthAlgTool(algname, name, ifc)
16 {
17 }
18 
20 {
21  ATH_MSG_INFO( "FPGATrackSimOverlapRemovalTool::initialize()" );
22 
23  if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
24 
25  // Check if this is 2nd stage
26  if(m_do2ndStage)
27  {
28  m_totLayers = m_FPGATrackSimMapping->PlaneMap_2nd(0)->getNLogiLayers();
29  }
30  else
31  {
32  m_totLayers = m_FPGATrackSimMapping->PlaneMap_1st(0)->getNLogiLayers();
33  }
34  ATH_MSG_DEBUG("Total number of layer: " << m_totLayers);
35 
36  // Check road OR
38  ATH_MSG_WARNING("LocalMaxOR only being run per hough slice (i.e. this tool does nothing) since roadSliceOR is turned off");
39 
40 
41  // Setup OR algorithm
42  if(m_algorithm == "Normal") m_algo=ORAlgo::Normal;
43  else if(m_algorithm == "Invert") m_algo=ORAlgo::InvertGrouping;
44  else
45  {
46  ATH_MSG_ERROR("initialize(): OR algorithm doesn't exist. ");
47  return StatusCode::FAILURE;
48  }
49  ATH_MSG_DEBUG("Overlap removal algorithm is "<<m_algorithm.value());
50 
51  return StatusCode::SUCCESS;
52 }
53 
54 bool isLocalMax(vector2D<FPGATrackSimRoad*> const & acc, unsigned x, unsigned y, int localMaxWindowSize)
55 {
56  if (!localMaxWindowSize) return true;
57  if (!acc(y, x)) return false;
58  for (int j = -localMaxWindowSize; j <= localMaxWindowSize; j++)
59  for (int i = -localMaxWindowSize; i <= localMaxWindowSize; i++)
60  {
61  if (i == 0 && j == 0) continue;
62  if (y + j < acc.size(0) && x + i < acc.size(1))
63  {
64  if (!acc(y+j, x+i)) continue;
65  if (acc(y+j, x+i)->getNHitLayers() > acc(y, x)->getNHitLayers()) return false;
66  if (acc(y+j, x+i)->getNHitLayers() == acc(y, x)->getNHitLayers())
67  {
68  if (acc(y+j, x+i)->getNHits() > acc(y, x)->getNHits()) return false;
69  if (acc(y+j, x+i)->getNHits() == acc(y, x)->getNHits() && j <= 0 && i <= 0) return false;
70  }
71  }
72  }
73 
74  return true;
75 }
76 
77 StatusCode FPGATrackSimOverlapRemovalTool::runOverlapRemoval(std::vector<std::shared_ptr<const FPGATrackSimRoad>>& roads)
78 {
79  if (roads.empty()) return StatusCode::SUCCESS;
80 
81  if (!m_roadSliceOR) return StatusCode::SUCCESS;
82  size_t in = roads.size();
83 
84  // Hough image
86 
87  // Slice-wise duplicate removal: accept only one road (with most hits) per bin
88  for (auto &r: roads)
89  {
90  FPGATrackSimRoad* & old = acc(r->getYBin(), r->getXBin());
91  if (!old) old = new FPGATrackSimRoad (*r.get());
92  else if (r->getNHitLayers() > old->getNHitLayers()) *old = *r.get();
93  else if (r->getNHitLayers() == old->getNHitLayers() && r->getNHits() > old->getNHits()) *old = *r.get();
94  }
95 
96  // Reformat to vector
97  roads.clear();
98  for (unsigned y = 0; y < m_imageSize_y; y++)
99  for (unsigned x = 0; x < m_imageSize_x; x++)
100  if (FPGATrackSimRoad *tempPtr = acc(y, x); tempPtr && isLocalMax(acc, x, y, m_localMaxWindowSize)/*All-slices local max*/) {
101  roads.emplace_back(std::shared_ptr<const FPGATrackSimRoad>(tempPtr));
102  acc(y, x) = nullptr;
103  }
104  else {
105  delete acc(y,x);
106  acc(y,x) = nullptr;
107  }
108 
109  ATH_MSG_DEBUG("Input: " << in << " Output: " << roads.size());
110  return StatusCode::SUCCESS;
111 }
112 
113 StatusCode FPGATrackSimOverlapRemovalTool::runOverlapRemoval(std::vector<FPGATrackSimTrack>& tracks)
114 {
115 
116  // Do fast OR instead of requested
117  if (m_doFastOR) return runOverlapRemoval_fast(tracks);
118 
119  // Otherwise, proceed
120  ATH_MSG_DEBUG("Beginning runOverlapRemoval()");
121 
122  ATH_MSG_DEBUG("Tracks in event: " << tracks.size());
123 
125 }
126 
127 
129 
130  // Hit comparison
131  struct HitCompare {
132  bool operator()(const FPGATrackSimHit* a, const FPGATrackSimHit* b) const {
133  auto hash_a = a->getIdentifierHash();
134  auto hash_b = b->getIdentifierHash();
135  if ( hash_a == hash_b ) {
136  auto phi_a = a->getPhiIndex();
137  auto phi_b = b->getPhiIndex();
138  if ( phi_a == phi_b ) {
139  auto eta_a = a->getEtaIndex();
140  auto eta_b = b->getEtaIndex();
141  if ( eta_a == eta_b) {
142  auto layer_a = a->getPhysLayer();
143  auto layer_b = b->getPhysLayer();
144  return layer_a < layer_b;
145  }
146  return eta_a < eta_b;
147  }
148  return phi_a < phi_b;
149  }
150  return hash_a < hash_b;
151  }
152  };
153 
154  std::set<const FPGATrackSimHit*, HitCompare > hitsInTrack1;
155  for ( auto& hit : track1.getFPGATrackSimHits()) {
156  if (hit.isReal()) hitsInTrack1.insert(&hit);
157  }
158 
159  std::set<const FPGATrackSimHit*, HitCompare> hitsInTrack2;
160  for ( auto& hit: track2.getFPGATrackSimHits()){
161  if (hit.isReal()) hitsInTrack2.insert(&hit);
162  }
163 
164  std::vector<const FPGATrackSimHit*> sharedHits;
165  std::set_intersection( hitsInTrack1.begin(), hitsInTrack1.end(),
166  hitsInTrack2.begin(), hitsInTrack2.end(),
167  std::back_inserter(sharedHits),
168  HitCompare() );
169 
170  // Number of real hits in track 1, number of real hits in track 2, number of shared hits, number of non-shared hits (?)
171  int nHitsInTrack1 = hitsInTrack1.size();
172  int nHitsInTrack2 = hitsInTrack2.size();
173  int nSharedHits = sharedHits.size();
174  // Original version seems to be only track 1; I want to compare each pair only once so
175  // let's make this the most conservative option (i.e. smallest number) ?
176  int nonOverlappingHits = std::min(nHitsInTrack1 - nSharedHits, nHitsInTrack2 - nSharedHits);
177 
178  // Now check if these pass our criteria for overlapping. If not, just return.
179  if(getAlgorithm() == ORAlgo::Normal) {
180  // Here decision is based on number of overlapping hits.
181  // Consider these overlapping if they share >= m_NumOfHitPerGrouping
182  if(nSharedHits < m_NumOfHitPerGrouping) return StatusCode::SUCCESS;
183 
184  } else if(getAlgorithm() == ORAlgo::InvertGrouping) {
185  // This is the opposite: duplicates of number of unique hits is <= m_NumOfHitPerGrouping.
186  if(nonOverlappingHits > m_NumOfHitPerGrouping) return StatusCode::SUCCESS;
187 
188  } else {
189  // Unknown.
190  return StatusCode::FAILURE;
191  }
192 
193  // Made it here: these tracks are overlapping.
194  // But we already sorted them such that track 2 is the one
195  // we want to keep, so we can just set track 1 to be removed.
196  track1.setPassedOR(0);
197 
198  return StatusCode::SUCCESS;
199 }
200 
202 {
203  std::vector<const FPGATrackSimHit*> hitsInTrack1;
204  for ( auto& hit : track1.getFPGATrackSimHits()) {
205  if (hit.isReal()) hitsInTrack1.push_back(&hit);
206  }
207 
208  std::vector<const FPGATrackSimHit*> hitsInTrack2;
209  for ( auto& hit: track2.getFPGATrackSimHits()){
210  if (hit.isReal()) hitsInTrack2.push_back(&hit);
211  }
212 
213  // If one track has more hits than the other, it's better.
214  // Return true if track 2 is better than track 1.
215  // Otherwise, decide based on chi2.
216  bool goodOrder = true;
217  if (hitsInTrack1.size() == hitsInTrack2.size()) {
218  // Surprising number of cases where the chi2 is actually identical.
219  // In these cases, let's default to the track ID number as the next most important property.
220  // So put it higher since we are considering later tracks to be better.
221  if (track1.getChi2ndof() == track2.getChi2ndof() && track1.getTrackID() < track2.getTrackID()) goodOrder = false;
222  // Now assuming they're different, we want them in decreasing chi2 order
223  else if (track1.getChi2ndof() < track2.getChi2ndof()) goodOrder = false;
224  } else if (hitsInTrack1.size() > hitsInTrack2.size()) {
225  goodOrder = false;
226  }
227 
228  return goodOrder;
229 
230 }
231 
233 {
234  ATH_MSG_DEBUG("Beginning fast overlap removal");
235 
236  // Sort tracks in order of increasing quality.
237  // This way, once a track has been eliminated in a comparison, we don't
238  // need to check it against any other tracks - they will always be
239  // better than it.
240  std::sort(std::begin(tracks),
241  std::end(tracks),
243 
244  // Now compare every pair of tracks.
245  // Set passedOR to 0 for the worst one (first one)
246  // if they are found to overlap.
247  for (unsigned int i=0; i < tracks.size(); i++) {
248 
249  // Skip track i if bad chi2.
250  if (tracks.at(i).getChi2ndof() > m_minChi2.value()) {
251  tracks.at(i).setPassedOR(0);
252  continue;
253  }
254 
255  // Now check against all other tracks.
256  for (unsigned int j=i+1; j< tracks.size(); j++) {
257 
258  // Uniquely comparing tracks i and j here.
259 
260  // If have set track i to 0 in a previous comparison,
261  // no need to look at it any more - we're done with it.
262  if (!tracks.at(i).passedOR()) break;
263 
264  // Ignore j if its chi2 is bad.
265  if (tracks.at(j).getChi2ndof() > m_minChi2.value()) tracks.at(j).setPassedOR(0);
266 
267  // If we just set track j to zero for bad chi2,
268  // no need to do the comparison.
269  if (!tracks.at(j).passedOR()) continue;
270 
271  // If we're still here, two at least semi-decent tracks.
272  // Compare them and remove one if necessary.
273  ATH_CHECK(removeOverlapping(tracks.at(i),tracks.at(j)));
274 
275  }
276  }
277 
278  return StatusCode::SUCCESS;
279 }
280 
281 
beamspotman.r
def r
Definition: beamspotman.py:672
FPGATrackSimOverlapRemovalTool::m_NumOfHitPerGrouping
Gaudi::Property< int > m_NumOfHitPerGrouping
Definition: FPGATrackSimOverlapRemovalTool.h:61
getMenu.algname
algname
Definition: getMenu.py:54
FPGATrackSimTrack::getTrackID
int getTrackID() const
Definition: FPGATrackSimTrack.h:32
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
FPGATrackSimOverlapRemovalTool::m_do2ndStage
Gaudi::Property< bool > m_do2ndStage
Definition: FPGATrackSimOverlapRemovalTool.h:60
FPGATrackSimTrack
Definition: FPGATrackSimTrack.h:18
FPGATrackSimPlaneMap.h
Maps physical layers to logical layers.
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
FPGATrackSimOverlapRemovalTool::FPGATrackSimOverlapRemovalTool
FPGATrackSimOverlapRemovalTool()=delete
FPGATrackSimOverlapRemovalTool::getAlgorithm
ORAlgo getAlgorithm() const
Definition: FPGATrackSimOverlapRemovalTool.h:51
FPGATrackSimOverlapRemovalTool::m_compareAllHits
Gaudi::Property< bool > m_compareAllHits
Definition: FPGATrackSimOverlapRemovalTool.h:69
ORAlgo::Normal
@ Normal
FPGATrackSimOverlapRemovalTool::m_doFastOR
Gaudi::Property< bool > m_doFastOR
Definition: FPGATrackSimOverlapRemovalTool.h:68
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
FPGATrackSimTrack::setPassedOR
void setPassedOR(unsigned int)
Definition: FPGATrackSimTrack.cxx:259
FPGATrackSimOverlapRemovalTool::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Definition: FPGATrackSimOverlapRemovalTool.h:70
FPGATrackSimOverlapRemovalTool::m_imageSize_x
Gaudi::Property< unsigned > m_imageSize_x
Definition: FPGATrackSimOverlapRemovalTool.h:65
FPGATrackSimOverlapRemovalTool::m_imageSize_y
Gaudi::Property< unsigned > m_imageSize_y
Definition: FPGATrackSimOverlapRemovalTool.h:66
x
#define x
isLocalMax
bool isLocalMax(vector2D< FPGATrackSimRoad * > const &acc, unsigned x, unsigned y, int localMaxWindowSize)
Definition: FPGATrackSimOverlapRemovalTool.cxx:54
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:92
FPGATrackSimHit
Definition: FPGATrackSimHit.h:41
FPGATrackSimTrack::getFPGATrackSimHits
const std::vector< FPGATrackSimHit > & getFPGATrackSimHits() const
Definition: FPGATrackSimTrack.h:63
FPGATrackSimVectors.h
Defines several vector wrappers for homogenous multi-dimensional vectors, declared as 1D arrays for l...
vector2D
Definition: FPGATrackSimVectors.h:28
FPGATrackSimOverlapRemovalTool::m_roadSliceOR
Gaudi::Property< bool > m_roadSliceOR
Definition: FPGATrackSimOverlapRemovalTool.h:63
FPGATrackSimTrack::getChi2ndof
float getChi2ndof() const
Definition: FPGATrackSimTrack.h:45
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
FPGATrackSimOverlapRemovalTool::m_algorithm
Gaudi::Property< std::string > m_algorithm
Definition: FPGATrackSimOverlapRemovalTool.h:67
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
FPGATrackSimOverlapRemovalTool::m_totLayers
int m_totLayers
Definition: FPGATrackSimOverlapRemovalTool.h:72
AthenaPoolTestRead.acc
acc
Definition: AthenaPoolTestRead.py:16
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
FPGATrackSimOverlapRemovalTool::m_minChi2
Gaudi::Property< float > m_minChi2
Definition: FPGATrackSimOverlapRemovalTool.h:62
FPGATrackSimOverlapRemovalTool::m_localMaxWindowSize
Gaudi::Property< int > m_localMaxWindowSize
Definition: FPGATrackSimOverlapRemovalTool.h:64
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
FPGATrackSimOverlapRemovalTool::m_FPGATrackSimMapping
ServiceHandle< IFPGATrackSimMappingSvc > m_FPGATrackSimMapping
Definition: FPGATrackSimOverlapRemovalTool.h:79
FPGATrackSimOverlapRemovalTool::m_algo
ORAlgo m_algo
Definition: FPGATrackSimOverlapRemovalTool.h:73
FPGATrackSimOverlapRemovalTool::compareTrackQuality
static bool compareTrackQuality(const FPGATrackSimTrack &track1, const FPGATrackSimTrack &track2)
Definition: FPGATrackSimOverlapRemovalTool.cxx:201
FPGATrackSimOverlapRemovalTool::runOverlapRemoval_fast
StatusCode runOverlapRemoval_fast(std::vector< FPGATrackSimTrack > &tracks)
Definition: FPGATrackSimOverlapRemovalTool.cxx:232
FPGATrackSimOverlapRemovalTool::removeOverlapping
StatusCode removeOverlapping(FPGATrackSimTrack &track1, FPGATrackSimTrack &track2)
Definition: FPGATrackSimOverlapRemovalTool.cxx:128
ORAlgo::InvertGrouping
@ InvertGrouping
a
TList * a
Definition: liststreamerinfos.cxx:10
y
#define y
runOverlapRemoval
StatusCode runOverlapRemoval(std::vector< FPGATrackSimTrack > &tracks, const float minChi2, const int NumOfHitPerGrouping, ORAlgo orAlgo, ToolHandle< GenericMonitoringTool > &monTool, bool compareAllHits=false)
Definition: FPGATrackSimHoughFunctions.cxx:15
CSV_InDetExporter.old
old
Definition: CSV_InDetExporter.py:145
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
FPGATrackSimOverlapRemovalTool::initialize
StatusCode initialize() override
Definition: FPGATrackSimOverlapRemovalTool.cxx:19
AthAlgTool
Definition: AthAlgTool.h:26
columnar::operator()
decltype(auto) operator()(ObjectId< CI, CM > id) const noexcept
Definition: ColumnAccessor.h:173
set_intersection
Set * set_intersection(Set *set1, Set *set2)
Perform an intersection of two sets.
FPGATrackSimRoad
Definition: FPGATrackSimRoad.h:31
FPGATrackSimOverlapRemovalTool::runOverlapRemoval
StatusCode runOverlapRemoval(std::vector< std::shared_ptr< const FPGATrackSimRoad >> &roads)
Definition: FPGATrackSimOverlapRemovalTool.cxx:77