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 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 
43 bool 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 
66 StatusCode 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 
102 StatusCode 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 
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.
168  if(getAlgorithm() == ORAlgo::Normal) {
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 
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 
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
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:43
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
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_algo
ORAlgo m_algo
Definition: FPGATrackSimOverlapRemovalTool.h:72
FPGATrackSimOverlapRemovalTool::compareTrackQuality
static bool compareTrackQuality(const FPGATrackSimTrack &track1, const FPGATrackSimTrack &track2)
Definition: FPGATrackSimOverlapRemovalTool.cxx:190
FPGATrackSimOverlapRemovalTool::runOverlapRemoval_fast
StatusCode runOverlapRemoval_fast(std::vector< FPGATrackSimTrack > &tracks)
Definition: FPGATrackSimOverlapRemovalTool.cxx:221
FPGATrackSimOverlapRemovalTool::removeOverlapping
StatusCode removeOverlapping(FPGATrackSimTrack &track1, FPGATrackSimTrack &track2)
Definition: FPGATrackSimOverlapRemovalTool.cxx:117
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:66