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