Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
FPGATrackSimClusteringTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3  */
4 
8 #include "CxxUtils/trapping_fp.h"
9 #include <algorithm>
10 #include <cmath>
11 
12 
13 namespace{
14  //For deciding eta || phi columns in modules
15  constexpr unsigned int ETA = 1;
16  constexpr unsigned int PHI = 0;
17 }
18 
19 FPGATrackSimClusteringTool::FPGATrackSimClusteringTool(const std::string& algname, const std::string &name, const IInterface *ifc) :
20  base_class(algname, name, ifc)
21 {
22 }
23 
24 
26 {
27  for (int i = 0; i<header.nTowers(); i++)
28  {
29  // Retreive the hits from the tower
30  FPGATrackSimTowerInputHeader& tower = *header.getTower(i);
31  std::vector<FPGATrackSimHit> hits = tower.hits();
32 
33  std::vector<std::vector<FPGATrackSimHit>> hitsPerModule;
34  std::vector<FPGATrackSimCluster> towerClusters;
35 
37  for (auto &hit : hits)
39  }
40 
41  splitAndSortHits(hits, hitsPerModule);
42  SortedClustering(hitsPerModule, towerClusters);
43  normaliseClusters(towerClusters);
44 
45  //remove the old hits from the tower...
46  tower.clearHits();
47  tower.reserveHits(towerClusters.size());
48  clusters.clear();
49  clusters.reserve(towerClusters.size());
50  if(i > 1)
51  ATH_MSG_WARNING("more than one tower, m_clusters is only going to contain those from the last one");
52 
53  unsigned cluster_count = 0;
54  unsigned int pixelCounter = 0;
55  unsigned int stripCounter = 0;
56  for ( auto &cluster: towerClusters){
59 
60  FPGATrackSimHit cluster_as_FPGATrackSimhit = cluster.getClusterEquiv();
61  cluster_as_FPGATrackSimhit.setHitType(HitType::clustered);
62  cluster_as_FPGATrackSimhit.setParentageMask(cluster_count); // making use of unused m_parentageMask to keep track of cluster index
63 
64  if(cluster_as_FPGATrackSimhit.getDetType() == SiliconTech::pixel)
65  {
66  cluster_as_FPGATrackSimhit.setCluster1ID(pixelCounter);
67  pixelCounter++;
68  }
69  else if(cluster_as_FPGATrackSimhit.getDetType() == SiliconTech::strip)
70  {
71  cluster_as_FPGATrackSimhit.setCluster1ID(stripCounter);
72  stripCounter++;
73  }
74  tower.addHit(cluster_as_FPGATrackSimhit);
75 
76  //send back a copy for monitoring and to check when writing out hits in each road
77  clusters.push_back(cluster);
78  cluster_count++;
79  }
80  }
81  ATH_MSG_DEBUG("Produced "<< clusters.size()<< " clusters");
82  return StatusCode::SUCCESS;
83 }
84 
85 //Attempt to implement clustering using FPGATrackSim objects.
86 void FPGATrackSimClusteringTool::SortedClustering(const std::vector<std::vector<FPGATrackSimHit> >& sorted_hits, std::vector<FPGATrackSimCluster> &clusters) const {
87  std::vector<FPGATrackSimCluster> moduleClusters;
88  //Loop over the sorted modules that we have
89  for( auto& moduleHits:sorted_hits){
90  //Make the clusters for this module
91  Clustering(moduleHits, moduleClusters);
92  //Put these clusters into the output list
93  clusters.insert(clusters.end(), moduleClusters.begin(), moduleClusters.end());
94  //Clear the vector or this will get messy
95  moduleClusters.clear();
96  }
97 }
98 
99 void FPGATrackSimClusteringTool::Clustering(std::vector<FPGATrackSimHit> moduleHits, std::vector<FPGATrackSimCluster> &moduleClusters) const {
100  std::vector<FPGATrackSimCluster> tempClusters;
101  FPGATrackSimHit clusterEquiv;
102  bool newCluster, newHit;
103 
104  //To hold the current cluster vars for comparison
105  //loop over the hits that we have been passed for this module
106  for( auto& hit: moduleHits){
107  bool is_clustered_hit = false;
108 
109  //Loop over the clusters we have already made, check if this hit should be added to them?
110  for( auto& cluster: tempClusters){
111  if(hit.isPixel()){
113  is_clustered_hit = true;
114  }
115  if(hit.isStrip()){
117  is_clustered_hit = true;
118  }
119  }
120 
121  //If it is the first hit or a not clustered hit, then start a new cluster and add it to the output vector
122  if((is_clustered_hit==0) or (tempClusters.size()==0)){
123  FPGATrackSimCluster cluster;
124  if(hit.isPixel()){
125  // No need to check the return code here
127  } else if(hit.isStrip()){
129  }
130  //Put this cluster into the output hits. Will update it in place.
131  tempClusters.push_back(cluster);
132  }
133  }
134 
135  // Merge overlapping clusters
136  for (auto& cluster : tempClusters) {
137  newCluster = true;
138 
139  for (auto& finalCluster : moduleClusters) {
140  int cPhi = cluster.getClusterEquiv().getPhiIndex();
141  int cPhiWidth = cluster.getClusterEquiv().getPhiWidth();
142  int cEta = cluster.getClusterEquiv().getEtaIndex();
143  int cEtaWidth = cluster.getClusterEquiv().getEtaWidth();
144  int fCPhi = finalCluster.getClusterEquiv().getPhiIndex();
145  int fCPhiWidth = finalCluster.getClusterEquiv().getPhiWidth();
146  int fCEta = finalCluster.getClusterEquiv().getEtaIndex();
147  int fCEtaWidth = finalCluster.getClusterEquiv().getEtaWidth();
148 
149  // check for overlap in phi
150  if ((fCPhi > cPhi + cPhiWidth - 1) ||
151  (cPhi > fCPhi + fCPhiWidth - 1))
152  continue;
153 
154  // check for overlap in eta
155  if ((fCEta > cEta + cEtaWidth - 1) ||
156  (cEta > fCEta + fCEtaWidth - 1))
157  continue;
158 
159  // remaining clusters are overlapping, check if clusters share hits
160  unsigned int sharedhits = 0;
161  for (auto & hit : cluster.getHitList()) {
162  newHit = true;
163  for (auto & finalHit : finalCluster.getHitList()) {
164  if (hit.getEtaIndex() == finalHit.getEtaIndex() &&
165  hit.getPhiIndex() == finalHit.getPhiIndex())
166  newHit = false;
167  }
168  if (!newHit) {
169  sharedhits++;
170  }
171  }
172 
173  if (sharedhits == 0)
174  continue;
175 
176  // Merge the clusters
177  newCluster = false;
178 
179  clusterEquiv = finalCluster.getClusterEquiv();
180 
181  // set new phi & phi width
182  if (cPhi < fCPhi) {
183  clusterEquiv.setPhiIndex(cPhi);
184  if (cPhi + cPhiWidth < fCPhi + fCPhiWidth)
185  clusterEquiv.setPhiWidth(fCPhiWidth + (fCPhi - cPhi));
186  else
187  clusterEquiv.setPhiWidth(cPhiWidth);
188  } else {
189  clusterEquiv.setPhiIndex(fCPhi);
190  if (!(cPhi + cPhiWidth < fCPhi + fCPhiWidth))
191  clusterEquiv.setPhiWidth(cPhiWidth + (cPhi - fCPhi));
192  else
193  clusterEquiv.setPhiWidth(fCPhiWidth);
194  }
195 
196  // set new eta & eta width
197  if (cEta < fCEta) {
198  clusterEquiv.setEtaIndex(cEta);
199  if (cEta + cEtaWidth < fCEta + fCEtaWidth)
200  clusterEquiv.setEtaWidth(fCEtaWidth + (fCEta - cEta));
201  else
202  clusterEquiv.setEtaWidth(cEtaWidth);
203  } else {
204  clusterEquiv.setEtaIndex(fCEta);
205  if (!(cEta + cEtaWidth < fCEta + fCEtaWidth))
206  clusterEquiv.setEtaWidth(cEtaWidth + (cEta - fCEta));
207  else
208  clusterEquiv.setEtaWidth(fCEtaWidth);
209  }
210 
211  finalCluster.setClusterEquiv(clusterEquiv);
212 
213  for (auto & hit : cluster.getHitList()) {
214  newHit = true;
215  for (auto & finalHit : finalCluster.getHitList()) {
216  if (hit.getEtaIndex() == finalHit.getEtaIndex() &&
217  hit.getPhiIndex() == finalHit.getPhiIndex())
218  newHit = false;
219  }
220  if (newHit) {
222  clusterEquiv = finalCluster.getClusterEquiv();
223  float xOld = clusterEquiv.getX();
224  float yOld = clusterEquiv.getY();
225  float zOld = clusterEquiv.getZ();
226  float xPhiOld = clusterEquiv.getPhiCoord();
227  float xEtaOld = clusterEquiv.getEtaCoord();
228  float cPhiOld = clusterEquiv.getCentroidPhiIndex();
229  float cEtaOld = clusterEquiv.getCentroidEtaIndex();
230  float xNew = hit.getX();
231  float yNew = hit.getY();
232  float zNew = hit.getZ();
233  float xPhiNew = hit.getPhiCoord();
234  float xEtaNew = hit.getEtaCoord();
235  float cPhiNew = hit.getPhiIndex() + 0.5;
236  float cEtaNew = hit.getEtaIndex() + 0.5;
237  int tot = clusterEquiv.getToT();
238  int totNew = hit.getToT();
239  if (m_digitalClustering) {
240  // n+1 because that is old + new now
241  int n = finalCluster.getHitList().size();
242  clusterEquiv.setX((xOld*n + xNew) / (n+1));
243  clusterEquiv.setY((yOld*n + yNew) / (n+1));
244  clusterEquiv.setZ((zOld*n + zNew) / (n+1));
245  clusterEquiv.setPhiCoord((xPhiOld*n + xPhiNew) / (n+1));
246  clusterEquiv.setEtaCoord((xEtaOld*n + xEtaNew) / (n+1));
247  clusterEquiv.setCentroidPhiIndex((cPhiOld*n + cPhiNew) / (n+1));
248  clusterEquiv.setCentroidEtaIndex((cEtaOld*n + cEtaNew) / (n+1));
249  } else {
250  clusterEquiv.setX((xOld*tot + xNew*totNew) / (tot+totNew));
251  clusterEquiv.setY((yOld*tot + yNew*totNew) / (tot+totNew));
252  clusterEquiv.setZ((zOld*tot + zNew*totNew) / (tot+totNew));
253  clusterEquiv.setPhiCoord((xPhiOld*tot + xPhiNew*totNew) / (tot+totNew));
254  clusterEquiv.setEtaCoord((xEtaOld*tot + xEtaNew*totNew) / (tot+totNew));
255  clusterEquiv.setCentroidPhiIndex((cPhiOld*tot + cPhiNew*totNew) / (tot+totNew));
256  clusterEquiv.setCentroidEtaIndex((cEtaOld*tot + cEtaNew*totNew) / (tot+totNew));
257  }
258  clusterEquiv.setToT(tot + totNew);
259  finalCluster.setClusterEquiv(clusterEquiv);
260  finalCluster.push_backHitList(hit);
261  }
262  }
263  }
264 
265  if (newCluster)
266  moduleClusters.push_back(cluster);
267  }
268 }
269 
270 void FPGATrackSimClusteringTool::splitAndSortHits(std::vector<FPGATrackSimHit> &hits, std::vector<std::vector<FPGATrackSimHit> > &hitsPerModule, int &eta_phi) const {
271  splitHitsToModules(hits, hitsPerModule);
272  sortHitsOnModules(hitsPerModule, eta_phi);
273 }
274 
275 void FPGATrackSimClusteringTool::splitAndSortHits(std::vector<FPGATrackSimHit> &hits, std::vector<std::vector<FPGATrackSimHit> > &hitsPerModule) const{
276  splitHitsToModules(hits, hitsPerModule);
277  sortHitsOnModules(hitsPerModule);
278 }
279 
280 /*Temporarilly sort the hits into module by module packets
281 */
282 void FPGATrackSimClusteringTool::splitHitsToModules(std::vector<FPGATrackSimHit> &hits, std::vector<std::vector<FPGATrackSimHit> > &hitsPerModule) const{
283  //To hold the current module
284  std::vector<FPGATrackSimHit> currentModule;
285  uint hashing = 0;
286  //Split the incoming hits into hits by module
287  for ( auto& hit:hits){
288  if(hashing == 0){
289  currentModule.push_back(hit);
290  hashing = hit.getIdentifierHash();
291  } else if (hit.getIdentifierHash() == hashing) {
292  currentModule.push_back(hit);
293  } else {
294  hitsPerModule.push_back(currentModule);
295  currentModule.clear();
296  hashing = hit.getIdentifierHash();
297  currentModule.push_back(hit);
298  }
299  }
300 
301  // Now push that last one
302  if (currentModule.size() > 0) hitsPerModule.push_back(currentModule);
303 }
304 
305 void FPGATrackSimClusteringTool::sortHitsOnModules(std::vector<std::vector<FPGATrackSimHit> > &hitsPerModule, int &eta_phi) const{
306  //Loop over the module separated hits
307  for ( auto& module:hitsPerModule){
308  //Work out if columns are ETA (1) || PHI (0)
309  if(etaOrPhi(module.at(0)) == true){
310  //Sort by ETA first
311  eta_phi = ETA;
312  if (module.size() > 1) {
313  if (module.at(0).isStrip())
314  std::stable_sort(module.begin(), module.end(), FPGATrackSimCLUSTERING::sortITkInputEta);
315  }
316  if (module.size() > 1) {
317  if (module.at(0).isStrip())
318  std::stable_sort(module.begin(), module.end(), FPGATrackSimCLUSTERING::sortITkInputPhi);
319  }
320  } else {
321  //Sort by PHI first
322  eta_phi = PHI;
323  if (module.size() > 1) {
324  if (module.at(0).isStrip())
325  std::stable_sort(module.begin(), module.end(), FPGATrackSimCLUSTERING::sortITkInputPhi);
326  }
327  if (module.size() > 1) {
328  if (module.at(0).isStrip())
329  std::stable_sort(module.begin(), module.end(), FPGATrackSimCLUSTERING::sortITkInputEta);
330  }
331  }
332  }
333 }
334 
335 void FPGATrackSimClusteringTool::sortHitsOnModules(std::vector<std::vector<FPGATrackSimHit> > &hitsPerModule) const{
336  //Loop over the module separated hits
337  for ( auto& module:hitsPerModule){
338  if (module.size() > 1) {
339  if (module.at(0).isStrip())
340  std::stable_sort(module.begin(), module.end(), FPGATrackSimCLUSTERING::sortITkInputEta);
341  }
342  if (module.size() > 1) {
343  if (module.at(0).isStrip())
344  std::stable_sort(module.begin(), module.end(), FPGATrackSimCLUSTERING::sortITkInputPhi);
345  }
346  }
347 }
348 
349 
350 
351 //Need to remove the fpgatracksim::scaleHitFactor and normalise the widths
352 void FPGATrackSimClusteringTool::normaliseClusters(std::vector<FPGATrackSimCluster> &clusters) const {
353  for( auto &cluster:clusters){
354  //Grab the cluster equiv
355  FPGATrackSimHit clusterEquiv = cluster.getClusterEquiv();
356  //Update the clusterEquiv's position and width
357  if(clusterEquiv.isStrip()){
358  //Clear the groupsize, set this to be one as we are only clustering one row.
359  clusterEquiv.setEtaWidth(1);
360  clusterEquiv.setPhiIndex(clusterEquiv.getPhiIndex()/fpgatracksim::scaleHitFactor);
361  clusterEquiv.setPhiWidth(clusterEquiv.getPhiWidth()+1);
362  } else {
363  // Nothing to normalise for pixel clusters
364  continue;
365  }
366  cluster.setClusterEquiv(clusterEquiv);
367  }
368 }
369 
370 
371 /*Function to work out if we need to sort by eta or phi first.
372  *Depends on the position and orientation of the module in the detector.
373  * Currently backwards engineered from the MC. Need to ask ITk people to confirm.
374  */
376 
377  /*This currently might get complicated as eta/phi ordering varies depending on the position in the detector.
378  * For ITK-20-00-00 Step 2.2 inclined duals layout, worked out by Naoki.
379  * Detector position | Module Type (# chip) | Column | Row |
380  * =============================================================================
381  * Barrel Layer 0 Eta module 1-6 | 2 (double) | eta | phi |
382  * Barrel Layer 0 Eta module 7-22 | 1 (single) | phi | eta |
383  * Barrel Layer 1 Eta module 1-6 | 3 (quad) | eta | phi |
384  * Barrel Layer 1 Eta module 7-19 | 3 | phi | eta |
385  * Barrel Layer 2 Eta module 1-11 | 3 | eta | phi |
386  * Barrel Layer 2 Eta module 12-22 | 2 | phi | eta |
387  * Barrel Layer 3 Eta module 1-12 | 3 | eta | phi |
388  * Barrel Layer 3 Eta module 13-25 | 2 | phi | eta |
389  * Barrel Layer 4 Eta module 1-13 | 3 | eta | phi |
390  * Barrel Layer 4 Eta module 14-26 | 2 | phi | eta |
391  * All Endcap modules | 3 | eta | phi |
392  * =============================================================================
393  * Module Type 1 = Single, 2, Dual, 3 Quad
394  * 328x400 blocks
395  * Hit type is essentially isPixel
396  * DetectorZone 0 = Barrel, -ive/+ive = endcaps
397  */
398 
399  //Check if the two hits are from the same module
400  //If it is not a barrel module then sort eta as column
402  return ETA;
403  }
404  //Otherwise it is a barrel module and now things get more complicated
405  else {
406  //Start by looking at what layer it is in
407  if (hit.getPhysLayer() == 0 || hit.getPhysLayer() == 1) {
408  if (hit.getEtaModule() <=6) {
409  return ETA;
410  } else {
411  return PHI;
412  }
413  } else if (hit.getPhysLayer() == 2) {
414  if (hit.getEtaModule() <=11) {
415  return ETA;
416  } else {
417  return PHI;
418  }
419  } else if (hit.getPhysLayer() == 3) {
420  if (hit.getEtaModule() <=12) {
421  return ETA;
422  } else {
423  return PHI;
424  }
425  } else if (hit.getPhysLayer() == 4) {
426  if (hit.getEtaModule() <=13) {
427  return ETA;
428  } else {
429  return PHI;
430  }
431  }
432  }
433  //Default to ETA, but shouldn't reach here
434  return ETA;
435 }
436 
437 
438 
439 void FPGATrackSimCLUSTERING::attachTruth(std::vector<FPGATrackSimHit> &hits){
440  for( auto& hit : hits) {
442  // record highest pt contribution to the combination (cluster
443  if(!hit.getTruth().isEmpty()) {
444  mt.add(hit.getTruth());
445  hit.setTruth(mt);
446  } else {
447  FPGATrackSimMultiTruth::Barcode uniquecode(hit.getEventIndex(), hit.getBarcode());
448  mt.maximize(uniquecode, hit.getBarcodePt());
449  hit.setTruth(mt);
450  }
451  }
452 } //record truth for each raw channel in the cluster
453 
454 /*
455  * This function is used in the FPGATrackSimClusteringTools to see if a new hit should be added to the current cluster under construction.
456  * It checks if the hit is in a number of positions w.r.t. the cluster being formed: up/right, down/right, above, right, or inside a cluster that has formed a horseshoe.
457  */
458 bool FPGATrackSimCLUSTERING::updatePixelCluster(FPGATrackSimCluster &currentCluster, FPGATrackSimHit &incomingHit, bool newCluster, bool digitalClustering){
459 
460  if(newCluster){
461  FPGATrackSimHit newHit = incomingHit;
462  newHit.setEtaIndex(incomingHit.getEtaIndex());
463  newHit.setPhiIndex(incomingHit.getPhiIndex());
464  newHit.setEtaCoord(incomingHit.getEtaCoord());
465  newHit.setPhiCoord(incomingHit.getPhiCoord());
466  newHit.setCentroidPhiIndex(incomingHit.getPhiIndex() + 0.5);
467  newHit.setCentroidEtaIndex(incomingHit.getEtaIndex() + 0.5);
468  newHit.setEtaWidth(1);
469  newHit.setPhiWidth(1);
470  //Set the initial clusterEquiv to be the incoming hit with double precision
471  currentCluster.setClusterEquiv(newHit);
472  //Add the current hit to the list of hits
473  currentCluster.push_backHitList(incomingHit);
474  //It doesn't really matter, as we will be at the end of the hit loop, but we did technically "cluster" this hit
475  return true;
476  } else {
477  int hitRow = incomingHit.getEtaIndex();
478  int hitCol = incomingHit.getPhiIndex();
479 
480  FPGATrackSimHit clusterEquiv = currentCluster.getClusterEquiv();
481  int clusterRow = clusterEquiv.getEtaIndex();
482  int clusterRowWidth = clusterEquiv.getEtaWidth();
483  int clusterCol = clusterEquiv.getPhiIndex();
484  int clusterColWidth = clusterEquiv.getPhiWidth();
485 
486  if ((hitCol == clusterCol + clusterColWidth) && (hitRow == clusterRow + clusterRowWidth)) {
487  clusterColWidth++;
488  clusterRowWidth++;
489 
490  return FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
491  } else if ((hitCol == clusterCol + clusterColWidth) && (hitRow == clusterRow - 1)) {
492  clusterColWidth++;
493  clusterRow--;
494  clusterRowWidth++;
495 
496  return FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
497  } else if ((hitCol >= clusterCol) && (hitCol < clusterCol + clusterColWidth) && (hitRow == clusterRow + clusterRowWidth)) {
498  clusterRowWidth++;
499 
500  return FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
501  } else if ((hitCol == clusterCol + clusterColWidth) && (hitRow >= clusterRow) && (hitRow < clusterRow + clusterRowWidth)) {
502  clusterColWidth++;
503 
504  return FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
505  } else if ((hitCol >= clusterCol) && (hitCol < clusterCol + clusterColWidth) && (hitRow == clusterRow - 1)) {
506  clusterRow--;
507  clusterRowWidth++;
508 
509  return FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
510  } else if ((hitCol == clusterCol - 1) && (hitRow == clusterRow - 1)) {
511  clusterCol--;
512  clusterColWidth++;
513  clusterRow--;
514  clusterRowWidth++;
515 
516  return FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
517  } else if ((hitCol == clusterCol - 1) && (hitRow >= clusterRow) && (hitRow < clusterRow + clusterRowWidth)) {
518  clusterCol--;
519  clusterColWidth++;
520 
521  return FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
522  } else if ((hitCol == clusterCol - 1) && (hitRow == clusterRow + clusterRowWidth)) {
523  clusterCol--;
524  clusterColWidth++;
525  clusterRowWidth++;
526 
527  return FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
528  } else if ((hitCol >= clusterCol) && (hitCol < clusterCol + clusterColWidth) && (hitRow >= clusterRow) && (hitRow < clusterRow + clusterRowWidth)) {
529  return FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
530  } else {
531  return false;
532  }
533  }
534 }
535 
536 /*
537  * This function is used in the FPGATrackSimClusteringTools to see if a new hit should be added to the current cluster under construction. It assumes double precision hits.
538  * It checks if the hit is in a number of positions w.r.t. the cluster being formed: up/right, down/right, above, right, or inside a cluster that has formed a horseshoe.
539  */
540 bool FPGATrackSimCLUSTERING::updateStripCluster(FPGATrackSimCluster &currentCluster, FPGATrackSimHit &incomingHit, bool newCluster, bool digitalClustering){
541 
543 
544  // Shift initial widths 1->0, 2->2, 3->4, 4->6 etc...
545  //The groupSize is stored in the EtaWidth
547  // Now shift to pixel width equivalents, 0->0, 2->1, 4->2, 6->3 etc...
548  if(tempWidth > 0) tempWidth = tempWidth/fpgatracksim::scaleHitFactor;
549  if(newCluster){
550  FPGATrackSimHit newHit = incomingHit;
551  //Double the precision of the strip positions.
552  int tempCentroid = incomingHit.getPhiIndex()*fpgatracksim::scaleHitFactor;
553  // Now shift the centroid phi+phiWidth, and store the width (put it back in the PhiWidth)
554  newHit.setPhiIndex(tempCentroid+tempWidth);
555  newHit.setPhiWidth(tempWidth);
556  //Set the initial clusterEquiv to be the incoming hit with double precision
557  currentCluster.setClusterEquiv(newHit);
558  //Add the current hit to the list of hits
559  currentCluster.push_backHitList(incomingHit);
560  //It doesn't really matter, as we will be at the end of the hit loop, but we did technically "cluster" this hit
561  return true;
562  } else {
563  //Now get the --START-- of the new strip cluster
564  int hitRow = incomingHit.getEtaIndex();
565  int hitCol = incomingHit.getPhiIndex()*fpgatracksim::scaleHitFactor;
566 
567  FPGATrackSimHit clusterEquiv = currentCluster.getClusterEquiv();
568  int clusterRow = clusterEquiv.getEtaIndex();
569  int clusterRowWidth = clusterEquiv.getEtaWidth();
570  int clusterCol = clusterEquiv.getPhiIndex();
571  int clusterColWidth = clusterEquiv.getPhiWidth();
572 
573  //Looking for a neighbour to the right. i.e. find the end of the current cluster (Col+width) and look in the next cell (+2). Compare this to the start of the new cluster. This is unlikely/impossible(?) to happen due to preclustering.
574  if(hitCol == clusterCol+clusterColWidth+fpgatracksim::scaleHitFactor && hitRow == clusterRow) {
575  //The new centroid will be the original column position, minus its width, plus the new width
576  //So subtract the original width...
577  clusterCol = clusterCol - clusterColWidth;
578  //The new width will be the combination of the current widths, ++
579  clusterColWidth = clusterColWidth+tempWidth+1;
580  //And add on the new width
581  clusterCol = clusterCol + clusterColWidth;
582  FPGATrackSimCLUSTERING::updateClusterContents(currentCluster, clusterRow, clusterRowWidth, clusterCol, clusterColWidth, incomingHit, digitalClustering);
583  return true;
584  } else return false;
585  }
586 }
587 
588 
589 bool FPGATrackSimCLUSTERING::updateClusterContents(FPGATrackSimCluster &currentCluster, int &clusterRow, int &clusterRowWidth, int &clusterCol, int &clusterColWidth, FPGATrackSimHit &incomingHit, bool digitalClustering) {
590  //Grab the cluster equiv
591  FPGATrackSimHit clusterEquiv = currentCluster.getClusterEquiv();
592  bool isConnected = false;
593 
594  //Check if connected to another hit in the cluster
595  if(incomingHit.isPixel()){
596  for (auto & hit : currentCluster.getHitList()) {
597  auto hitEta = hit.getEtaIndex();
598  auto hitPhi = hit.getPhiIndex();
599  auto inHitEta = incomingHit.getEtaIndex();
600  auto inHitPhi = incomingHit.getPhiIndex();
601 
602  if (((inHitEta == hitEta - 1) && (inHitPhi == hitPhi - 1)) ||
603  ((inHitEta == hitEta + 1) && (inHitPhi == hitPhi - 1)) ||
604  ((inHitEta == hitEta - 1) && (inHitPhi == hitPhi + 1)) ||
605  ((inHitEta == hitEta + 1) && (inHitPhi == hitPhi + 1)) ||
606  ((inHitEta == hitEta) && (inHitPhi == hitPhi - 1)) ||
607  ((inHitEta == hitEta) && (inHitPhi == hitPhi + 1)) ||
608  ((inHitEta == hitEta - 1) && (inHitPhi == hitPhi)) ||
609  ((inHitEta == hitEta + 1) && (inHitPhi == hitPhi))) {
610  isConnected = true;
611  break;
612  }
613  }
614  if (!isConnected)
615  return false;
616  }
617 
618  //Update the clusterEquiv's position and width
619  clusterEquiv.setEtaIndex(clusterRow);
620  clusterEquiv.setEtaWidth(clusterRowWidth);
621  clusterEquiv.setPhiIndex(clusterCol);
622  clusterEquiv.setPhiWidth(clusterColWidth);
623 
624 
625  float xOld = clusterEquiv.getX();
626  float yOld = clusterEquiv.getY();
627  float zOld = clusterEquiv.getZ();
628  float xPhiOld = clusterEquiv.getPhiCoord();
629  float xEtaOld = clusterEquiv.getEtaCoord();
630  float cPhiOld = clusterEquiv.getCentroidPhiIndex();
631  float cEtaOld = clusterEquiv.getCentroidEtaIndex();
632  float xNew = incomingHit.getX();
633  float yNew = incomingHit.getY();
634  float zNew = incomingHit.getZ();
635  float xPhiNew = incomingHit.getPhiCoord();
636  float xEtaNew = incomingHit.getEtaCoord();
637  float cPhiNew = incomingHit.getPhiIndex() + 0.5;
638  float cEtaNew = incomingHit.getEtaIndex() + 0.5;
639  int tot = clusterEquiv.getToT();
640  int totNew = incomingHit.getToT();
641  //As strips arrive pre-clustered, this is different for pixels/strips
642  if(incomingHit.isPixel()){
644  if (digitalClustering) {
645  // n+1 because that is old + new now
646  int n = currentCluster.getHitList().size();
647  clusterEquiv.setX((xOld*n + xNew) / (n+1));
648  clusterEquiv.setY((yOld*n + yNew) / (n+1));
649  clusterEquiv.setZ((zOld*n + zNew) / (n+1));
650  clusterEquiv.setPhiCoord((xPhiOld*n + xPhiNew) / (n+1));
651  clusterEquiv.setEtaCoord((xEtaOld*n + xEtaNew) / (n+1));
652  clusterEquiv.setCentroidPhiIndex((cPhiOld*n + cPhiNew) / (n+1));
653  clusterEquiv.setCentroidEtaIndex((cEtaOld*n + cEtaNew) / (n+1));
654  } else {
655  clusterEquiv.setX((xOld*tot + xNew*totNew) / (tot+totNew));
656  clusterEquiv.setY((yOld*tot + yNew*totNew) / (tot+totNew));
657  clusterEquiv.setZ((zOld*tot + zNew*totNew) / (tot+totNew));
658  clusterEquiv.setPhiCoord((xPhiOld*tot + xPhiNew*totNew) / (tot+totNew));
659  clusterEquiv.setEtaCoord((xEtaOld*tot + xEtaNew*totNew) / (tot+totNew));
660  clusterEquiv.setCentroidPhiIndex((cPhiOld*tot + cPhiNew*totNew) / (tot+totNew));
661  clusterEquiv.setCentroidEtaIndex((cEtaOld*tot + cEtaNew*totNew) / (tot+totNew));
662  }
663  } else {
664  //Phi width + 1 for the seed is the width of the current cluster
665  int N = currentCluster.getClusterEquiv().getPhiWidth()+1;
666  //Phi width of an incoming strip is the width of the cluster
667  int newN = incomingHit.getPhiWidth();
668  //Now as above, N+newN
669  clusterEquiv.setX((xOld*N + xNew*newN) / (N+newN));
670  clusterEquiv.setY((yOld*N + yNew*newN) / (N+newN));
671  clusterEquiv.setZ((zOld*N + zNew*newN) / (N+newN));
672  }
673  clusterEquiv.setToT(tot + totNew);
674 
675  //Put it back
676  currentCluster.setClusterEquiv(clusterEquiv);
677 
678  //Pushback the hit into the hitlist
679  currentCluster.push_backHitList(incomingHit);
680 
681  return true;
682 }
683 
684 /* Sort for the ordering of ITk modules: Sort by ETA.
685 */
687 {
688  if (hitA.getIdentifierHash() != hitB.getIdentifierHash())
689  return hitA.getIdentifierHash() < hitB.getIdentifierHash();
690  return hitA.getEtaIndex() < hitB.getEtaIndex();
691 }
692 
693 /* Sort for the ordering of ITk modules: Sort by PHI.
694 */
696 {
697  if (hitA.getIdentifierHash() != hitB.getIdentifierHash())
698  return hitA.getIdentifierHash() < hitB.getIdentifierHash();
699  return hitA.getPhiIndex() < hitB.getPhiIndex();
700 }
701 
702 /* Cap precision of the global coordinates in r, phi, z */
704  FPGATrackSimHit clusterEquiv = cluster.getClusterEquiv();
705  float pos[3] = { clusterEquiv.getR(), clusterEquiv.getGPhi(), clusterEquiv.getZ() };
706 
707  pos[0] = std::trunc(pos[0] / m_coordRPrecision) * m_coordRPrecision;
708  pos[1] = std::trunc(pos[1] / m_coordPhiPrecision) * m_coordPhiPrecision;
709  pos[2] = std::trunc(pos[2] / m_coordZPrecision) * m_coordZPrecision;
710 
711  clusterEquiv.setX(pos[0] * std::cos(pos[1]));
712  clusterEquiv.setY(pos[0] * std::sin(pos[1]));
713  clusterEquiv.setZ(pos[2]);
714 
715  cluster.setClusterEquiv(clusterEquiv);
716 }
717 
719  float pos[3] = { hit.getR(), hit.getGPhi(), hit.getZ() };
720 
721  pos[0] = std::trunc(pos[0] / m_coordRPrecision) * m_coordRPrecision;
722  pos[1] = std::trunc(pos[1] / m_coordPhiPrecision) * m_coordPhiPrecision;
723  pos[2] = std::trunc(pos[2] / m_coordZPrecision) * m_coordZPrecision;
724 
725  hit.setX(pos[0] * std::cos(pos[1]));
726  hit.setY(pos[0] * std::sin(pos[1]));
727  hit.setZ(pos[2]);
728 }
FPGATrackSimCLUSTERING::updateStripCluster
bool updateStripCluster(FPGATrackSimCluster &currentCluster, FPGATrackSimHit &incomingHit, bool newCluster, bool digitalClustering)
Definition: FPGATrackSimClusteringTool.cxx:540
FPGATrackSimTowerInputHeader::clearHits
void clearHits()
Definition: FPGATrackSimTowerInputHeader.h:49
CXXUTILS_TRAPPING_FP
#define CXXUTILS_TRAPPING_FP
Definition: trapping_fp.h:24
FPGATrackSimClusteringTool::sortHitsOnModules
void sortHitsOnModules(std::vector< std::vector< FPGATrackSimHit > > &hitsPerModule, int &eta_phi) const
Definition: FPGATrackSimClusteringTool.cxx:305
getMenu.algname
algname
Definition: getMenu.py:54
FPGATrackSimLogicalEventInputHeader
Definition: FPGATrackSimLogicalEventInputHeader.h:21
FPGATrackSimCluster::getHitList
hitVector const & getHitList() const
Definition: FPGATrackSimCluster.h:30
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
SiliconTech::strip
@ strip
FPGATrackSimHit::isStrip
bool isStrip() const
Definition: FPGATrackSimHit.h:65
header
Definition: hcg.cxx:526
FPGATrackSimHit::getPhysLayer
unsigned getPhysLayer() const
Definition: FPGATrackSimHit.cxx:69
FPGATrackSimHit::getToT
unsigned getToT() const
Definition: FPGATrackSimHit.h:155
FPGATrackSimCLUSTERING::sortITkInputPhi
bool sortITkInputPhi(const FPGATrackSimHit &hitA, const FPGATrackSimHit &HitB)
Definition: FPGATrackSimClusteringTool.cxx:695
FPGATrackSimCLUSTERING::attachTruth
void attachTruth(std::vector< FPGATrackSimHit > &)
Definition: FPGATrackSimClusteringTool.cxx:439
FPGATrackSimCluster
Definition: FPGATrackSimCluster.h:24
FPGATrackSimHit::setEtaIndex
void setEtaIndex(unsigned v)
Definition: FPGATrackSimHit.h:102
FPGATrackSimCLUSTERING::updatePixelCluster
bool updatePixelCluster(FPGATrackSimCluster &currentCluster, FPGATrackSimHit &incomingHit, bool newCluster, bool digitalClustering)
Definition: FPGATrackSimClusteringTool.cxx:458
FPGATrackSimHit::setPhiCoord
void setPhiCoord(float v)
Definition: FPGATrackSimHit.h:105
FPGATrackSimHit::setCentroidPhiIndex
void setCentroidPhiIndex(float v)
Definition: FPGATrackSimHit.h:103
FPGATrackSimHit::getX
float getX() const
Definition: FPGATrackSimHit.h:140
FPGATrackSimCLUSTERING::updateClusterContents
bool updateClusterContents(FPGATrackSimCluster &currentCluster, int &clusterRow, int &clusterRowWidth, int &clusterCol, int &clusterColWidth, FPGATrackSimHit &incomingHit, bool digitalClustering)
Definition: FPGATrackSimClusteringTool.cxx:589
FPGATrackSimHit::setEtaWidth
void setEtaWidth(unsigned v)
Definition: FPGATrackSimHit.h:78
FPGATrackSimMultiTruth.h
JetTiledMap::N
@ N
Definition: TiledEtaPhiMap.h:44
FPGATrackSimHit::getEtaModule
int getEtaModule() const
Definition: FPGATrackSimHit.h:87
FPGATrackSimClusteringTool::m_coordPhiPrecision
Gaudi::Property< float > m_coordPhiPrecision
Definition: FPGATrackSimClusteringTool.h:46
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
RoiUtil::PHI
@ PHI
Definition: RoiSerialise.cxx:31
FPGATrackSimHit::setY
void setY(float v)
Definition: FPGATrackSimHit.h:138
FPGATrackSimCluster::setClusterEquiv
void setClusterEquiv(const FPGATrackSimHit &input)
Definition: FPGATrackSimCluster.h:35
FPGATrackSimConstants.h
FPGATrackSimTowerInputHeader::addHit
void addHit(const FPGATrackSimHit &s)
Definition: FPGATrackSimTowerInputHeader.h:48
FPGATrackSimHit
Definition: FPGATrackSimHit.h:41
FPGATrackSimHit::getGPhi
float getGPhi() const
Definition: FPGATrackSimHit.h:144
FPGATrackSimClusteringTool::etaOrPhi
bool etaOrPhi(const FPGATrackSimHit &hit) const
Definition: FPGATrackSimClusteringTool.cxx:375
FPGATrackSimHit::getPhiCoord
float getPhiCoord() const
Definition: FPGATrackSimHit.h:111
python.PyAthena.module
module
Definition: PyAthena.py:131
FPGATrackSimHit::setX
void setX(float v)
Definition: FPGATrackSimHit.h:137
uint
unsigned int uint
Definition: LArOFPhaseFill.cxx:20
FPGATrackSimHit::setToT
void setToT(unsigned v)
Definition: FPGATrackSimHit.h:148
FPGATrackSimHit::setPhiIndex
void setPhiIndex(unsigned v)
Definition: FPGATrackSimHit.h:101
FPGATrackSimHit::getPhiIndex
unsigned getPhiIndex() const
Definition: FPGATrackSimHit.h:107
lumiFormat.i
int i
Definition: lumiFormat.py:85
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
FPGATrackSimMultiTruth::add
void add(const FPGATrackSimMultiTruth::Barcode &code, const FPGATrackSimMultiTruth::Weight &weight)
Definition: FPGATrackSimMultiTruth.cxx:22
FPGATrackSimHit::setEtaCoord
void setEtaCoord(float v)
Definition: FPGATrackSimHit.h:106
FPGATrackSimMultiTruth::Barcode
std::pair< unsigned long, unsigned long > Barcode
Definition: FPGATrackSimMultiTruth.h:49
FPGATrackSimClusteringTool::normaliseClusters
void normaliseClusters(std::vector< FPGATrackSimCluster > &clusters) const
Definition: FPGATrackSimClusteringTool.cxx:352
FPGATrackSimCLUSTERING::sortITkInputEta
bool sortITkInputEta(const FPGATrackSimHit &hitA, const FPGATrackSimHit &hitB)
Definition: FPGATrackSimClusteringTool.cxx:686
FPGATrackSimHit::getY
float getY() const
Definition: FPGATrackSimHit.h:141
FPGATrackSimHit::getEtaIndex
unsigned getEtaIndex() const
Definition: FPGATrackSimHit.h:108
FPGATrackSimHit::getIdentifierHash
unsigned getIdentifierHash() const
Definition: FPGATrackSimHit.h:81
FPGATrackSimHit::isPixel
bool isPixel() const
Definition: FPGATrackSimHit.h:64
FPGATrackSimClusteringTool::m_coordZPrecision
Gaudi::Property< float > m_coordZPrecision
Definition: FPGATrackSimClusteringTool.h:47
FPGATrackSimClusteringTool::FPGATrackSimClusteringTool
FPGATrackSimClusteringTool(const std::string &, const std::string &, const IInterface *)
Definition: FPGATrackSimClusteringTool.cxx:19
FPGATrackSimHit::setCluster1ID
void setCluster1ID(int v)
Definition: FPGATrackSimHit.h:182
FPGATrackSimHit::getZ
float getZ() const
Definition: FPGATrackSimHit.h:142
FPGATrackSimHit::getDetectorZone
DetectorZone getDetectorZone() const
Definition: FPGATrackSimHit.h:59
trapping_fp.h
Tell the compiler to optimize assuming that FP may trap.
FPGATrackSimMultiTruth::maximize
void maximize(const FPGATrackSimMultiTruth::Barcode &code, const FPGATrackSimMultiTruth::Weight &weight)
Definition: FPGATrackSimMultiTruth.cxx:36
FPGATrackSimMultiTruth
Definition: FPGATrackSimMultiTruth.h:46
FPGATrackSimCluster::getClusterEquiv
FPGATrackSimHit const & getClusterEquiv() const
Definition: FPGATrackSimCluster.h:31
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
FPGATrackSimClusteringTool::SortedClustering
void SortedClustering(const std::vector< std::vector< FPGATrackSimHit > > &sorted_hits, std::vector< FPGATrackSimCluster > &) const
Definition: FPGATrackSimClusteringTool.cxx:86
FPGATrackSimHit::getCentroidPhiIndex
float getCentroidPhiIndex() const
Definition: FPGATrackSimHit.h:109
HitType::clustered
@ clustered
FPGATrackSimClusteringTool::m_reduceCoordPrecision
Gaudi::Property< bool > m_reduceCoordPrecision
Definition: FPGATrackSimClusteringTool.h:44
FPGATrackSimHit::setPhiWidth
void setPhiWidth(unsigned v)
Definition: FPGATrackSimHit.h:79
RoiUtil::ETA
@ ETA
Definition: RoiSerialise.cxx:30
FPGATrackSimClusteringTool::splitAndSortHits
void splitAndSortHits(std::vector< FPGATrackSimHit > &hits, std::vector< std::vector< FPGATrackSimHit > > &hitsPerModule, int &eta_phi) const
Definition: FPGATrackSimClusteringTool.cxx:270
FPGATrackSimHit::getEtaCoord
float getEtaCoord() const
Definition: FPGATrackSimHit.h:112
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
FPGATrackSimHit::setZ
void setZ(float v)
Definition: FPGATrackSimHit.h:139
FPGATrackSimClusteringTool::m_digitalClustering
Gaudi::Property< bool > m_digitalClustering
Definition: FPGATrackSimClusteringTool.h:43
FPGATrackSimHit::getCentroidEtaIndex
float getCentroidEtaIndex() const
Definition: FPGATrackSimHit.h:110
fpgatracksim::scaleHitFactor
constexpr float scaleHitFactor
Definition: FPGATrackSimConstants.h:18
FPGATrackSimHit::getR
float getR() const
Definition: FPGATrackSimHit.h:143
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
FPGATrackSimClusteringTool::splitHitsToModules
void splitHitsToModules(std::vector< FPGATrackSimHit > &hits, std::vector< std::vector< FPGATrackSimHit > > &hitsPerModule) const
Definition: FPGATrackSimClusteringTool.cxx:282
FPGATrackSimTowerInputHeader::reserveHits
void reserveHits(size_t size)
Definition: FPGATrackSimTowerInputHeader.h:50
FPGATrackSimClusteringTool.h
FPGATrackSimHit::getDetType
SiliconTech getDetType() const
Definition: FPGATrackSimHit.h:58
RunTileMonitoring.clusters
clusters
Definition: RunTileMonitoring.py:133
DetectorZone::barrel
@ barrel
FPGATrackSimHit::getEtaWidth
unsigned getEtaWidth() const
Definition: FPGATrackSimHit.h:85
FPGATrackSimClusteringTool::DoClustering
virtual StatusCode DoClustering(FPGATrackSimLogicalEventInputHeader &, std::vector< FPGATrackSimCluster > &) const override
Definition: FPGATrackSimClusteringTool.cxx:25
FPGATrackSimTowerInputHeader::hits
const std::vector< FPGATrackSimHit > & hits() const
Definition: FPGATrackSimTowerInputHeader.h:46
FPGATrackSimClusteringTool::reduceGlobalCoordPrecision
void reduceGlobalCoordPrecision(FPGATrackSimCluster &cluster) const
Definition: FPGATrackSimClusteringTool.cxx:703
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
FPGATrackSimHit::setCentroidEtaIndex
void setCentroidEtaIndex(float v)
Definition: FPGATrackSimHit.h:104
FPGATrackSimHit::setParentageMask
void setParentageMask(unsigned long v)
Definition: FPGATrackSimHit.h:153
FPGATrackSimTowerInputHeader
Definition: FPGATrackSimTowerInputHeader.h:18
FPGATrackSimHit::getPhiWidth
unsigned getPhiWidth() const
Definition: FPGATrackSimHit.h:86
FPGATrackSimCluster::push_backHitList
void push_backHitList(const FPGATrackSimHit &input)
Definition: FPGATrackSimCluster.h:38
SiliconTech::pixel
@ pixel
FPGATrackSimHit::setHitType
void setHitType(HitType type)
Definition: FPGATrackSimHit.h:54
FPGATrackSimClusteringTool::m_coordRPrecision
Gaudi::Property< float > m_coordRPrecision
Definition: FPGATrackSimClusteringTool.h:45
FPGATrackSimClusteringTool::Clustering
void Clustering(std::vector< FPGATrackSimHit >, std::vector< FPGATrackSimCluster > &) const
Definition: FPGATrackSimClusteringTool.cxx:99