ATLAS Offline Software
Loading...
Searching...
No Matches
FPGATrackSimHoughFunctions.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3 */
4
6
11
14
16
18
19#include <stdexcept>
20
21using namespace asg::msgUserCode;
22
23// EPSILON for hit position float comparisons
24constexpr float EPSILON = 1e-5;
25
26StatusCode runOverlapRemoval(std::vector<FPGATrackSimTrack>& tracks, const float minChi2, const int NumOfHitPerGrouping, ORAlgo orAlgo, ToolHandle<GenericMonitoringTool> & monTool, bool compareAllHits)
27{
28 ANA_MSG_DEBUG("Beginning runOverlapRemoval()");
29 ANA_MSG_DEBUG("Tracks in event: " << tracks.size());
30
31 std::vector<int> flags_OR;
32 flags_OR.clear();
33
34 // Debug variables
35 int ntrack_passOR = 0;
36 int ntrack = 0;
37 std::vector<int> track_passOR_counter(tracks.size(), -1);
38 std::vector<int> track_passOR_barcodefrac(tracks.size(), -1);
39 int ntrack_passOR_total = 0;
40 int trackMuon_gt0pt5_passOR = 0;
41 float tmp_TrueTrack_BCF = -999;
42
43 // Pre-filter tracks with bad chi2
44 std::vector<unsigned int> goodTrackIndices;
45 goodTrackIndices.reserve(tracks.size());
46 for(unsigned int i = 0; i < tracks.size(); i++)
47 {
48 if(tracks[i].getChi2ndof() > minChi2)
49 {
50 tracks[i].setPassedOR(0);
51 }
52 else
53 {
54 goodTrackIndices.push_back(i);
55 }
56 }
57
58 // Pre-compute track_counter based on chi2 cuts (static per event, doesn't depend on track pairs)
59 std::vector<int> track_counter;
60 int ntr_belowMinChi2 = 0;
61 for(unsigned int i=0; i<tracks.size();i++)
62 {
63 if(tracks.at(i).getChi2ndof() > minChi2) {
64 track_counter.push_back(0);
65 flags_OR.push_back(-1);
66 } else {
67 ntr_belowMinChi2++;
68 track_counter.push_back(ntr_belowMinChi2);
69 flags_OR.push_back(1);
70 }
71 }
72
73 // Create tracks to hold and compare - only process good tracks
74 for(size_t idx = 0; idx < goodTrackIndices.size(); idx++)
75 {
76 unsigned int i = goodTrackIndices[idx];
77 FPGATrackSimTrack &fit1 = tracks.at(i);
78
79 // Skip if already marked as failed
80 if(!fit1.passedOR()) continue;
81
82 // Create vector for holding duplicate track list
83 std::vector<int> duplicates(1,i);
84
85 // Loop through ALL other good tracks (not just those after)
86 for(size_t jdx = 0; jdx < goodTrackIndices.size(); jdx++)
87 {
88 if(jdx == idx) continue; // Skip comparing with itself
89
90 unsigned int j = goodTrackIndices[jdx];
91 FPGATrackSimTrack &fit2 = tracks.at(j);
92
93 // Based on the algorithm choose common hit of non-common hit
94 if(orAlgo == ORAlgo::Normal)
95 {
96 // Find the number of common hits between two tracks. We have two ways to do this:
97 // * only compare hits in the same 'layer', requires tracks to be the same size.
98 // * compare every hit to every other hit; allows for tracks to be different sizes.
99 int nOverlappingHits = 0;
100 nOverlappingHits = (compareAllHits) ? findNCommonHitsGlobal(fit1, fit2) : findNCommonHits(fit1, fit2);
101
102 // Group overlapping tracks into a vector for removal if at least [NumOfHitPerGrouping] hits are the same
103 if(nOverlappingHits >= NumOfHitPerGrouping)
104 {
105 duplicates.push_back(j);
106 }
107 }
108 else if(orAlgo == ORAlgo::InvertGrouping)
109 {
110 // Find the number of non-common hits between two tracks using coordinate comparison
111 int nNotOverlappingHits = 0;
112 nNotOverlappingHits = findNonOverlapHits(fit1, fit2);
113
114 // If the number of non-overlapping hit is [NumOfHitPerGrouping] or less
115 if(nNotOverlappingHits <= NumOfHitPerGrouping)
116 {
117 duplicates.push_back(j);
118 }
119 }
120 }
121 findMinChi2MaxHit(duplicates, tracks, flags_OR, track_counter);
122
123
124 // Monitoring
125 ntrack++;
126 track_passOR_counter[i] = ntrack;
127 // barcodeFrac should be set in the track upstream e.g in FPGATrackSimLogicalHitsProcessAlg.cxx using calculateTruth()
128 if (fit1.getBarcodeFrac() < 0)
129 ANA_MSG_WARNING("barcodeFrac not set!");
130 track_passOR_barcodefrac[i] = fit1.getBarcodeFrac();
131 // check if the track passes OR and has barcodeFrac > 0.5
132 if(fit1.getBarcodeFrac() > 0.5 && fit1.passedOR()) {
133 // count how many muon tracks satisfy the condition
134 trackMuon_gt0pt5_passOR++;
135 // for the first passing track, record its barcodeFrac
136 if(trackMuon_gt0pt5_passOR == 1) {
137 tmp_TrueTrack_BCF = fit1.getBarcodeFrac();
138 }
139 // for subsequent passing tracks, keep the largest barcodeFrac
140 else if (fit1.getBarcodeFrac() > tmp_TrueTrack_BCF) {
141 tmp_TrueTrack_BCF = fit1.getBarcodeFrac();
142 }
143 }
144
145 }
146
147 // Monitoring histograms
148 ANA_MSG_DEBUG("List of tracks passing OR:: ");
149 for(unsigned int i=0; i<tracks.size();i++){
150 FPGATrackSimTrack &fit1 = tracks.at(i);
151 if(fit1.passedOR()) {
152 ntrack_passOR++;
153 ANA_MSG_DEBUG("track# = " << track_passOR_counter[i] << ": chi2 = " << fit1.getChi2ndof() << " barcodefrac = " << track_passOR_barcodefrac[i]);
154 }
155 }
156 ntrack_passOR_total += ntrack_passOR;
157 auto mon_ntrack_passOR = Monitored::Scalar<int>("ntrack_passOR", ntrack_passOR);
158 auto mon_barcodeFrac_passOR = Monitored::Scalar<int>("barcodeFrac_passOR", tmp_TrueTrack_BCF);
159 Monitored::Group(monTool, mon_ntrack_passOR);
160 Monitored::Group(monTool, mon_barcodeFrac_passOR);
161 ANA_MSG_DEBUG("Number of tracks passing OR (total) = " << ntrack_passOR_total);
162
163
164 return StatusCode::SUCCESS;
165}
166
168{
169 int nonOverlapHits=0;
170
171 // Loop through all layers
172 const auto& hits1 = Track1.getFPGATrackSimHitPtrs();
173 const auto& hits2 = Track2.getFPGATrackSimHitPtrs();
174
175 for(size_t i = 0; i < hits1.size() && i < hits2.size(); ++i)
176 {
177 if (!hits1[i] || !hits2[i]) throw std::runtime_error("Null hit pointer in findNonOverlapHits: hit is null, tracks should not have unassigned layers");
178
179 const FPGATrackSimHit& hit1 = *hits1[i];
180 const FPGATrackSimHit& hit2 = *hits2[i];
181 // First make sure we are looking at real hits
182 if(!hit1.isReal() || !hit2.isReal())
183 {
184 continue;
185 }
186 // Check if two hits are on the same plane
187 else if(hit1.getLayer() != hit2.getLayer())
188 {
189 nonOverlapHits++;
190 }
191 // Check if two hits have the same hashID
192 else if(hit1.getIdentifierHash() != hit2.getIdentifierHash())
193 {
194 nonOverlapHits++;
195 }
196 // Check if two hits have same coordinate. this is difficult due to spacepoints,
197 // since the same hit can be used to make multiple spacepoints.
198 else if (hit1.getHitType() == HitType::spacepoint && hit2.getHitType() == HitType::spacepoint) {
199 if ((abs(hit1.getX() - hit2.getX()) > EPSILON) || (abs(hit1.getY() - hit2.getY()) > EPSILON) || (abs(hit1.getZ() - hit2.getZ()) > EPSILON)) {
200 nonOverlapHits++;
201 } else {
202 continue;
203 }
204 }
205 else if (std::abs(hit1.getGPhi()-hit2.getGPhi())>0.001 && std::abs(hit1.getZ()-hit2.getZ())>0.001 && std::abs(hit1.getR()-hit2.getR())>0.001)
206 {
207 nonOverlapHits++;
208 }
209 else
210 {
211 continue;
212 }
213 }
214 return nonOverlapHits;
215}
216
217
218void findMinChi2MaxHit(const std::vector<int>& duplicates, std::vector<FPGATrackSimTrack>& RMtracks, std::vector<int>& flags_OR, const std::vector<int>& track_counter)
219{
220 int dup_counter = 0;
221 int head_track = 1;
222 float head_chi2 = 0.;
223 int head_nhits = 0;
224
225 for(auto dup: duplicates)
226 {
227 float t_chi2 = RMtracks.at(dup).getChi2ndof();
228 const auto& hits = RMtracks.at(dup).getFPGATrackSimHitPtrs();
229 int t_nhitlayers = hits.size();
230 for(const auto& hit_ptr : hits)
231 {
232 if (!hit_ptr) throw std::runtime_error("Null hit pointer in findMinChi2MaxHit: hit is null");
233 const auto& hit = *hit_ptr;
234 ANA_MSG_DEBUG("Real hit info = " << hit);
235 ANA_MSG_DEBUG("Real hit info (global) = Gphi= " << hit.getGPhi() << " Z=" << hit.getZ() << " R=" << hit.getR() << " chi2=" << t_chi2);
236
237 if(!hit.isReal())
238 {
239 t_nhitlayers--;
240 }
241 }
242 if (dup_counter == 0) {
243 head_track = dup;
244 head_chi2 = RMtracks.at(head_track).getChi2ndof();
245 head_nhits = t_nhitlayers;
246 }
247 if (dup_counter > 0){
248 if(t_nhitlayers>head_nhits)
249 {
250 RMtracks.at(head_track).setPassedOR(0);
251 }
252 else if(t_nhitlayers==head_nhits)
253 {
254 if((head_chi2-t_chi2)>0.000001)
255 {
256 RMtracks.at(head_track).setPassedOR(0);
257 }
258 if(std::abs(t_chi2-head_chi2)<0.000001)
259 {
260 if(track_counter[head_track] < track_counter[dup]) {
261 RMtracks.at(dup).setPassedOR(0);
262 }
263 if(track_counter[head_track] > track_counter[dup]) {
264 RMtracks.at(head_track).setPassedOR(0);
265 }
266 }
267 }
268 }
269
270 if(!RMtracks.at(head_track).passedOR()) flags_OR[head_track] = 0;
271 if(RMtracks.at(head_track).passedOR()) flags_OR[head_track] = 1;
272 dup_counter++;
273
274 }
275}
276// New algorithm which loops over all of the hits in track 1 to compare to each hit in track 2
278{
279 int nCommHits = 0;
280 const auto& hits1 = Track1.getFPGATrackSimHitPtrs();
281 const auto& hits2 = Track2.getFPGATrackSimHitPtrs();
282 std::vector<uint8_t> hit2_matched(hits2.size(), 0);
283
284 for (const auto& hit1_ptr : hits1)
285 {
286 if (!hit1_ptr) throw std::runtime_error("Null hit pointer in findNCommonHits_v2: hit1 is null");
287 if (!hit1_ptr->isReal()) continue; // Skip if hit1 is not real
288 const auto& hit1 = *hit1_ptr;
289
290 for (size_t j = 0; j < hits2.size(); ++j)
291 {
292 if (!hits2[j]) throw std::runtime_error("Null hit pointer in findNCommonHits_v2: hit2 is null");
293 const auto& hit2 = *hits2[j];
294
295 if (hit2_matched[j]) continue; // already used this hit
296 else if (!hit2.isReal()) continue; // Check if hit is missing
297 else if (hit1.getLayer() != hit2.getLayer()) continue; // Check if hit on the same plane
298 else if (hit1.getIdentifierHash() != hit2.getIdentifierHash()) continue; // Check if two hits have the same hashID
299
300 // Check if two hits have same coordinate. this is difficult due to spacepoints,
301 // since the same hit can be used to make multiple spacepoints.
302 else if (hit1.getHitType() == HitType::spacepoint && hit2.getHitType() == HitType::spacepoint)
303 {
304 if (std::abs(hit1.getX() - hit2.getX()) < EPSILON &&
305 std::abs(hit1.getY() - hit2.getY()) < EPSILON &&
306 std::abs(hit1.getZ() - hit2.getZ()) < EPSILON)
307 {
308 nCommHits++;
309 hit2_matched[j] = true;
310 break;
311 }
312 }
313
314 // If both hits aren't spacepoints, we should be able to do this comparison.
315 else if (std::abs(hit1.getGPhi() - hit2.getGPhi()) < 0.001 &&
316 std::abs(hit1.getZ() - hit2.getZ()) < 0.001 &&
317 std::abs(hit1.getR() - hit2.getR()) < 0.001)
318 {
319 nCommHits++;
320 hit2_matched[j] = true;
321 break;
322 }
323 }
324 }
325
326 return nCommHits;
327}
328
329// New algorithm which loops over all of the hits in track 1 to compare to each hit in track 2
331{
332 int nCommHits = 0;
333 const auto& hits1 = Track1.getFPGATrackSimHitPtrs();
334 const auto& hits2 = Track2.getFPGATrackSimHitPtrs();
335 std::vector<uint8_t> hit2_matched(hits2.size(), 0);
336
337 for (const auto& hit1_ptr : hits1)
338 {
339 if (!hit1_ptr) throw std::runtime_error("Null hit pointer in findNCommonHitsGlobal: hit1 is null, tracks should not have unassigned layers");
340 if (!hit1_ptr->isReal()) continue; // Skip if hit1 is not real
341 const auto& hit1 = *hit1_ptr;
342
343 for (size_t j = 0; j < hits2.size(); ++j)
344 {
345 if (!hits2[j]) throw std::runtime_error("Null hit pointer in findNCommonHitsGlobal: hit2 is null, tracks should not have unassigned layers");
346 const auto& hit2 = *hits2[j];
347
348 if (hit2_matched[j]) continue; // already used this hit
349 else if (!hit2.isReal()) continue; // Check if hit is missing
350 else if (hit1.getLayer() != hit2.getLayer()) continue; // Check if hit on the same plane
351 else if (hit1.getIdentifierHash() != hit2.getIdentifierHash()) continue; // Check if two hits have the same hashID
352
353 // Check if two hits have same coordinate. this is difficult due to spacepoints,
354 // since the same hit can be used to make multiple spacepoints.
355 else if (hit1.getHitType() == HitType::spacepoint && hit2.getHitType() == HitType::spacepoint)
356 {
357 if (std::abs(hit1.getX() - hit2.getX()) < EPSILON &&
358 std::abs(hit1.getY() - hit2.getY()) < EPSILON &&
359 std::abs(hit1.getZ() - hit2.getZ()) < EPSILON)
360 {
361 nCommHits++;
362 hit2_matched[j] = true;
363 break;
364 }
365 }
366
367 // If both hits aren't spacepoints, we should be able to do this comparison.
368 else if (std::abs(hit1.getGPhi() - hit2.getGPhi()) < EPSILON &&
369 std::abs(hit1.getZ() - hit2.getZ()) < EPSILON &&
370 std::abs(hit1.getR() - hit2.getR()) < EPSILON)
371 {
372 nCommHits++;
373 hit2_matched[j] = true;
374 break;
375 }
376 }
377 }
378
379 return nCommHits;
380}
381
382int findNCommonHits(const FPGATrackSimTrack& Track1, const FPGATrackSimTrack& Track2)
383{
384 int nCommHits=0;
385
386 // Loop through all layers
387 const auto& hits1 = Track1.getFPGATrackSimHitPtrs();
388 const auto& hits2 = Track2.getFPGATrackSimHitPtrs();
389
390 for(unsigned int i = 0; i < hits1.size() && i < hits2.size(); ++i)
391 {
392 if (!hits1[i] || !hits2[i]) throw std::runtime_error("Null hit pointer in findNCommonHits: tracks should not have unassigned layers");
393 const FPGATrackSimHit& hit1 = *hits1.at(i);
394 const FPGATrackSimHit& hit2 = *hits2.at(i);
395
396 // Check if hit is missing
397 if(!hit1.isReal() || !hit2.isReal())
398 {
399 continue;
400 }
401 // Check if hit on the same plane
402 else if(hit1.getLayer() != hit2.getLayer())
403 {
404 continue;
405 }
406 // Check if two hits have the same hashID
407 else if(hit1.getIdentifierHash() != hit2.getIdentifierHash())
408 {
409 continue;
410 }
411 // Check if two hits have same coordinate. this is difficult due to spacepoints,
412 // since the same hit can be used to make multiple spacepoints.
413 else if (hit1.getHitType() == HitType::spacepoint && hit2.getHitType() == HitType::spacepoint) {
414
415 if ((std::abs(hit1.getX() - hit2.getX()) < EPSILON) && (std::abs(hit1.getY() - hit2.getY()) < EPSILON) && (std::abs(hit1.getZ() - hit2.getZ()) < EPSILON)) {
416 nCommHits++;
417 } else {
418 continue;
419 }
420 }
421 // If both hits aren't spacepoints, we should be able to do this comparison.
422 else if (std::abs(hit1.getGPhi()-hit2.getGPhi())<0.001 && std::abs(hit1.getZ()-hit2.getZ())<0.001 && std::abs(hit1.getR()-hit2.getR())<0.001) {
423 nCommHits++;
424 }
425 else
426 {
427 continue;
428 }
429 }
430 return nCommHits;
431}
432
433
434// Given road, populates the supplied variables with info on which layers missed hits
435void getMissingInfo(const FPGATrackSimRoad & road, int & nMissing, bool & missPixel, bool & missStrip, layer_bitmask_t & missing_mask, layer_bitmask_t & norecovery_mask, const ServiceHandle<IFPGATrackSimMappingSvc> &FPGATrackSimMapping, const TrackCorrType idealCoordFitType)
436{
437 int subregion = road.getSubRegion();
438 nMissing = FPGATrackSimMapping->PlaneMap_1st(subregion)->getNCoords(); // init with nCoords and decrement as we find misses
439 missPixel = false;
440 missStrip = false;
441 missing_mask = 0;
442 norecovery_mask = 0;
443 unsigned int wclayers = road.getWCLayers();
444 for (unsigned layer = 0; layer < FPGATrackSimMapping->PlaneMap_1st(subregion)->getNLogiLayers(); layer++)
445 {
446 int nHits = road.getHitPtrs(layer).size();
447 if (nHits==0)
448 {
449 if (idealCoordFitType == TrackCorrType::None && ((wclayers >> layer) & 1))
450 {
451 int ix = FPGATrackSimMapping->PlaneMap_1st(subregion)->getCoordOffset(layer);
452 int iy = ix + 1;
453 if (FPGATrackSimMapping->PlaneMap_1st(subregion)->isSCT(layer))
454 {
455 missing_mask |= 1 << ix;
456 nMissing -= 1;
457 }
458 else
459 {
460 missing_mask |= (1<<ix) | (1<<iy);
461 nMissing -= 2;
462 }
463 }
464 else
465 {
466 if (FPGATrackSimMapping->PlaneMap_1st(subregion)->isSCT(layer)) missStrip = true;
467 else missPixel = true;
468 }
469 }
470 else if (!((wclayers >> layer) & 1)) { // we have a hit
471 int ix = FPGATrackSimMapping->PlaneMap_1st(subregion)->getCoordOffset(layer);
472 int iy = ix + 1;
473 if (FPGATrackSimMapping->PlaneMap_1st(subregion)->isSCT(layer))
474 {
475 missing_mask |= 1 << ix;
476 nMissing -= 1;
477 }
478 else
479 {
480 missing_mask |= (1<<ix) | (1<<iy);
481 nMissing -= 2;
482 }
483
484 }
485 }
486}
487
488
497void makeTrackCandidates(const FPGATrackSimRoad & road, const FPGATrackSimTrack & temp, std::vector<FPGATrackSimTrack>& track_cands, const ServiceHandle<IFPGATrackSimMappingSvc> & FPGATrackSimMapping)
498{
499 int idbase = 0; // offset for new track ids
500 int subregion = road.getSubRegion();
501 auto pmap = FPGATrackSimMapping->PlaneMap_2nd(subregion);
502
503 if (temp.getTrackStage() == TrackStage::FIRST) {
504 pmap = FPGATrackSimMapping->PlaneMap_1st(subregion);
505 }
506
507 std::vector<std::vector<int>> combs = ::getComboIndices(road.getNHits_layer());
508 track_cands.resize(combs.size(), temp);
509
510 const FPGATrackSimRegionMap* SUBREGIONMAP = FPGATrackSimMapping->SubRegionMap_2nd();
511 //
512 //get the WC hits:
513 layer_bitmask_t wcbits= road.getWCLayers();
514 // Add the hits from each combination to the track, and set ID
515 for (size_t icomb = 0; icomb < combs.size(); icomb++)
516 {
517 //Need to set the ID and the hits size of this track
518 track_cands[icomb].setTrackID(idbase + icomb);
519 track_cands[icomb].setNLayers(pmap->getNLogiLayers());
520
521 // If this is an idealized coordinate fit; keep references to the idealized radii.
522 track_cands[icomb].setIdealRadii(SUBREGIONMAP->getAvgRadii(subregion));
523 track_cands[icomb].setPassedOR(1);
524
525 std::vector<int> const & hit_indices = combs[icomb]; // size nLayers
526 for (unsigned layer = 0; layer < pmap->getNLogiLayers(); layer++)
527 {
528 if (hit_indices[layer] < 0) // Set a dummy hit if road has no hits in this layer
529 {
531 newhit.setLayer(layer);
532 newhit.setSection(0);
533 if (pmap->getDim(layer) == 2) newhit.setDetType(SiliconTech::pixel);
534 else newhit.setDetType(SiliconTech::strip);
535
536 if (wcbits & (1 << layer ) ) {
538 newhit.setLayer(layer);
539 }
540
541 track_cands[icomb].setFPGATrackSimHit(layer, std::make_shared<FPGATrackSimHit>(newhit));
542 }
543 else
544 {
545 const std::shared_ptr<const FPGATrackSimHit> hit = road.getHitPtrs(layer)[hit_indices[layer]];
546 // If this is an outer spacepoint, and it is not the same as the inner spacepoint, reject it.
547 // Here we "reject" it by marking the candidate as "invalid", to be rejected later.
548 // That require another field on the track object, but it avoids having to change the sizes
549 // of arrays computed above.
550 if (hit->getHitType() == HitType::spacepoint && (hit->getPhysLayer(true) % 2) == 1) {
551 if (layer == 0) throw (std::out_of_range("makeTrackCandidates: Attempt to access vector at element -1"));
552 auto inner_hit_ptr = track_cands[icomb].getFPGATrackSimHitPtrs().at(layer - 1);
553 if (!inner_hit_ptr) throw std::runtime_error("Null inner hit pointer in makeTrackCandidates: inner layer should have a hit when comparing spacepoints");
554 const FPGATrackSimHit & inner_hit = *inner_hit_ptr;
555 if ((abs(hit->getX() - inner_hit.getX()) > EPSILON) || (abs(hit->getY() - inner_hit.getY()) > EPSILON) || (abs(hit->getZ() - inner_hit.getZ()) > EPSILON)) {
556 track_cands[icomb].setValidCand(false);
557 }
558 }
559 track_cands[icomb].setFPGATrackSimHit(layer, std::move(hit));
560 }
561 }
562 }
563
564 idbase += combs.size();
565}
566
567
569{
570 // Custom labelling for the detector volumes
571 // to be used in NN training.
572 // Convention:
573 // barrel | else
574 //-------------------------------------
575 // Pixel | 0 | 2*sign(z)
576 // Strip | 10 | 10 + 2*sign(z)
577 //
578 // Explicitly:
579 // -2: C-side (-z) end cap pixel
580 // 0: barrel pixel
581 // 2: A-side (+z) end cap pixel
582 // 8: C-side end cap strip
583 // 10: barrel strip
584 // 12: A-sde end cap strip
585 // returns -999 if not a real hit
586
587
588 long volumeID = -1;
589
590 if (hit.getR() == 0.0) {
591 return -999; //hit not in any physical layer
592 }
593
594 if(hit.isBarrel()) {
595 if (hit.isPixel()) {
596 volumeID = 0;
597 }
598 if (hit.isStrip()) {
599 volumeID = 10;
600 }
601 }
602 else {
603 if (hit.isPixel()) {
604 if (hit.getZ() >= 0.) {
605 volumeID = 2;
606 }
607 else {
608 volumeID = -2;
609 }
610 }
611 else if (hit.isStrip()) {
612 if (hit.getZ() >= 0.) {
613 volumeID = 12;
614 }
615 else {
616 volumeID = 8;
617 }
618 }
619 }
620 return volumeID;
621}
622
624{
625 // Custom labelling for the detector layers
626 // to be used in NN training.
627 // This aims at providing a continuous numbering according to this convention:
628 // strip barrel layers in [0,3]
629 // strip C-side end cap layers in [4,9]
630 // strip A-side end cap layers in [10,15]
631 // pixel barrel layers in [16,20]
632 // pixel C-side end cap layers in [21,29]
633 // pixel A-side end cap layers > 30
634 // returns large negative value if no layer
635
636 long volumeID = getVolumeID(hit);
637 unsigned layerID = hit.getLayerDisk(true);
638
639 long offset = -10000;
640
641 if(volumeID == 10) offset = 0; //strip barrel
642 if(volumeID == 8) offset = 4; //strip -ve EC
643 if(volumeID == 12) offset = 10; //strip +ve EC
644 if(volumeID == 0) offset = 16; // pix barrel
645 if(volumeID == -2) offset = 21; //pix -ve EC
646 if(volumeID == 2) offset = 30; //pix +ve EC
647 return offset + layerID;
648}
649
651{
652 return (ID < 16);
653}
654
656{
657 return !isFineIDInStrip(ID);
658}
659
660long getFineID(const FPGATrackSimHit & hit)
661{
662 // Custom labelling for the detector layers
663 // to be used in NN training.
664 // Returns a labelling of non-barrel pixel hits similar to a hit's eta index,
665 // but with a continuous numbering.
666 // Otherwise return convention defined in getCoarseID.
667
668 long volumeID = getVolumeID(hit);
669 unsigned layerID = hit.getLayerDisk(true);
670 int etaID = hit.getEtaModule(true);
671
672 long offset = -1000;
673
674 if(volumeID == 10) return getCoarseID(hit); //strip barrel
675 if(volumeID == 8) return getCoarseID(hit); //strip -ve EC
676 if(volumeID == 12) return getCoarseID(hit); //strip +ve EC
677 if(volumeID == 0) return getCoarseID(hit); //pix barrel
678 if(volumeID == -999) return -999; //hit not in any physical layer
679 if(volumeID == -2)
680 {
681 if(layerID == 0) offset = 21;
682 if(layerID == 1) offset = 21+15;
683 if(layerID == 2) offset = 21+15+6;
684 if(layerID == 3) offset = 21+15+6+23;
685 if(layerID == 4) offset = 21+15+6+23+6;
686 if(layerID == 5) offset = 21+15+6+23+6+11;
687 if(layerID == 6) offset = 21+15+6+23+6+11+8;
688 if(layerID == 7) offset = 21+15+6+23+6+11+8+8;
689 if(layerID == 8) offset = 21+15+6+23+6+11+8+8+9;
690 return offset + etaID;
691 }
692 if(volumeID == 2)
693 {
694 if(layerID == 0) offset = 116;
695 if(layerID == 1) offset = 116+15;
696 if(layerID == 2) offset = 116+15+6;
697 if(layerID == 3) offset = 116+15+6+23;
698 if(layerID == 4) offset = 116+15+6+23+6;
699 if(layerID == 5) offset = 116+15+6+23+6+11;
700 if(layerID == 6) offset = 116+15+6+23+6+11+8;
701 if(layerID == 7) offset = 116+15+6+23+6+11+8+8;
702 if(layerID == 8) offset = 116+15+6+23+6+11+8+8+9;
703 return offset + etaID;
704 }
705
706 return -1;
707}
708
709// Adapted from TrackFitter, but TrackFitter *depends* on fit constants and this algorithm
710void roadsToTrack(std::vector<FPGATrackSimRoad>& roads, std::vector<FPGATrackSimTrack>& track_cands, const FPGATrackSimPlaneMap *pmap)
711{
712
713
714 for (const FPGATrackSimRoad& road : roads) {
715
717 temp.setNLayers(pmap->getNLogiLayers());
718 temp.setBankID(-1);
719 temp.setPatternID(road.getPID());
720 temp.setHoughX(road.getX());
721 temp.setHoughY(road.getY());
722 temp.setQOverPt(road.getY());
723
724 temp.setSubRegion(road.getSubRegion());
725 temp.setHoughXBin(road.getXBin());
726 temp.setHoughYBin(road.getYBin());
727 temp.setChi2(0);
728
729 temp.setBinIdx(road.getBinIdx());
730
731 // This comes from FPGATrackSimFunctions
732 std::vector<std::vector<int>> combs = getComboIndices(road.getNHits_layer());
733 unsigned existing_size = track_cands.size();
734 track_cands.resize(existing_size + combs.size(), temp);
735
736 //get the WC hits:
737 layer_bitmask_t wcbits= road.getWCLayers();
738 // Add the hits from each combination to the track, and set ID
739 for (size_t icomb = 0; icomb < combs.size(); icomb++)
740 {
741 if ((existing_size + icomb) >= track_cands.size()) continue;
742 track_cands[existing_size + icomb].setNLayers(pmap->getNLogiLayers());
743 std::vector<int> const & hit_indices = combs[icomb]; // size nLayers
744 for (unsigned layer = 0; layer < pmap->getNLogiLayers(); layer++)
745 {
746 if (hit_indices[layer] < 0) // Set a dummy hit if road has no hits in this layer
747 {
749 newhit.setLayer(layer);
750 newhit.setSection(0);
751 if (pmap->getDim(layer) == 2) newhit.setDetType(SiliconTech::pixel);
752 else newhit.setDetType(SiliconTech::strip);
753
754 if (wcbits & (1 << layer ) ) {
756 newhit.setLayer(layer);
757 }
758
759 track_cands[existing_size + icomb].setFPGATrackSimHit(layer, std::make_shared<FPGATrackSimHit>(newhit));
760 }
761 else
762 {
763 const std::shared_ptr<const FPGATrackSimHit> hit = road.getHitPtrs(layer)[hit_indices[layer]];
764 // If this is an outer spacepoint, and it is not the same as the inner spacepoint, reject it.
765 // Here we "reject" it by marking the candidate as "invalid", to be rejected later.
766 // That require another field on the track object, but it avoids having to change the sizes
767 // of arrays computed above.
768 if (hit->getHitType() == HitType::spacepoint && (hit->getPhysLayer() % 2) == 1 && (layer>0)) {
769 auto inner_hit_ptr = track_cands[existing_size + icomb].getFPGATrackSimHitPtrs().at(layer - 1);
770 if (!inner_hit_ptr) throw std::runtime_error("Null inner hit pointer in roadsToTrack: inner layer should have a hit when comparing spacepoints");
771 const FPGATrackSimHit & inner_hit = *inner_hit_ptr;
772 if ((std::abs(hit->getX() - inner_hit.getX()) > EPSILON) || (std::abs(hit->getY() - inner_hit.getY()) > EPSILON) || (std::abs(hit->getZ() - inner_hit.getZ()) > EPSILON)) {
773 track_cands[existing_size + icomb].setValidCand(false);
774 }
775 }
776 track_cands[existing_size + icomb].setFPGATrackSimHit(layer, std::move(hit));
777 }
778 }
779 }
780 }
781}
782
std::vector< Identifier > ID
macros for messaging and checking status codes
#define ANA_MSG_WARNING(xmsg)
Macro printing warning messages.
#define ANA_MSG_DEBUG(xmsg)
Macro printing debug messages.
std::vector< std::vector< int > > getComboIndices(std::vector< size_t > const &sizes)
Given a vector of sizes (of arrays), generates a vector of all combinations of indices to index one e...
: FPGATrackSim-specific class to represent an hit in the detector.
void findMinChi2MaxHit(const std::vector< int > &duplicates, std::vector< FPGATrackSimTrack > &RMtracks, std::vector< int > &flags_OR, const std::vector< int > &track_counter)
bool isFineIDInStrip(long ID)
long getFineID(const FPGATrackSimHit &hit)
void getMissingInfo(const FPGATrackSimRoad &road, int &nMissing, bool &missPixel, bool &missStrip, layer_bitmask_t &missing_mask, layer_bitmask_t &norecovery_mask, const ServiceHandle< IFPGATrackSimMappingSvc > &FPGATrackSimMapping, const TrackCorrType idealCoordFitType)
constexpr float EPSILON
int findNonOverlapHits(const FPGATrackSimTrack &Track1, const FPGATrackSimTrack &Track2)
int findNCommonHits_v2(const FPGATrackSimTrack &Track1, const FPGATrackSimTrack &Track2)
long getCoarseID(const FPGATrackSimHit &hit)
StatusCode runOverlapRemoval(std::vector< FPGATrackSimTrack > &tracks, const float minChi2, const int NumOfHitPerGrouping, ORAlgo orAlgo, ToolHandle< GenericMonitoringTool > &monTool, bool compareAllHits)
long getVolumeID(const FPGATrackSimHit &hit)
int findNCommonHitsGlobal(const FPGATrackSimTrack &Track1, const FPGATrackSimTrack &Track2)
void makeTrackCandidates(const FPGATrackSimRoad &road, const FPGATrackSimTrack &temp, std::vector< FPGATrackSimTrack > &track_cands, const ServiceHandle< IFPGATrackSimMappingSvc > &FPGATrackSimMapping)
Creates a list of track candidates by taking all possible combination of hits in road.
bool isFineIDInPixel(long ID)
void roadsToTrack(std::vector< FPGATrackSimRoad > &roads, std::vector< FPGATrackSimTrack > &track_cands, const FPGATrackSimPlaneMap *pmap)
int findNCommonHits(const FPGATrackSimTrack &Track1, const FPGATrackSimTrack &Track2)
Maps physical layers to logical layers.
Maps ITK module indices to FPGATrackSim regions.
Defines a class for roads.
uint32_t layer_bitmask_t
TrackCorrType
Header file to be included by clients of the Monitored infrastructure.
static const uint32_t nHits
float getY() const
void setLayer(unsigned v)
unsigned getIdentifierHash() const
float getX() const
void setHitType(HitType type)
float getGPhi() const
bool isBarrel() const
int getEtaModule(bool old=false) const
float getZ() const
float getR() const
unsigned getLayerDisk(bool old=false) const
bool isReal() const
bool isPixel() const
void setSection(unsigned v)
bool isStrip() const
HitType getHitType() const
void setDetType(SiliconTech detType)
uint32_t getNLogiLayers() const
uint32_t getDim(size_t logiLayer) const
const std::vector< double > & getAvgRadii(unsigned region) const
int getSubRegion() const
const std::vector< std::shared_ptr< const FPGATrackSimHit > > & getHitPtrs(size_t layer) const
layer_bitmask_t getWCLayers() const
std::vector< size_t > getNHits_layer() const
float getBarcodeFrac() const
unsigned int passedOR() const
const std::vector< std::shared_ptr< const FPGATrackSimHit > > & getFPGATrackSimHitPtrs() const
float getChi2ndof() const
void setNLayers(int)
set the number of layers in the track.
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.