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
650bool isFineIDInStrip(long ID)
651{
652 return (ID < 16);
653}
654
655bool isFineIDInPixel(long ID)
656{
657 return !isFineIDInStrip(ID);
658}
659
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
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
bool hit(const Container &ids, int pdgId)
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
float getZ() const
float getR() const
bool isReal() const
void setSection(unsigned v)
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.