ATLAS Offline Software
Loading...
Searching...
No Matches
FPGATrackSimMatrixGenAlgo.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
9
10
11#include "GaudiKernel/MsgStream.h"
12#include "GaudiKernel/ITHistSvc.h"
20
21#include "TH1.h"
22#include "TH2.h"
23#include "TStyle.h"
24
25#include <cassert>
26#include <sstream>
27#include <iostream>
28#include <fstream>
29#include <cmath>
30#include <utility>
31
32
34// Constructors
36
37FPGATrackSimMatrixGenAlgo::FPGATrackSimMatrixGenAlgo(const std::string& name, ISvcLocator* pSvcLocator) :
38 AthAlgorithm(name, pSvcLocator)
39{
40}
41
42
43
45// Initialize
47
49{
50 ATH_MSG_DEBUG("initialize()");
51
52 // set the slicing variables from inputs
53 m_sliceMax.qOverPt = m_temp_c_max;
58
59 m_sliceMin.qOverPt = m_temp_c_min;
64
65 m_nBins.qOverPt = m_temp_c_slices;
70
71 // Retrieve handles
72 ATH_CHECK(m_tHistSvc.retrieve());
74 ATH_CHECK(m_hitInputTool.retrieve());
75 ATH_CHECK(m_hitMapTool.retrieve());
76 ATH_CHECK(m_EvtSel.retrieve());
77 ATH_CHECK(m_roadFinderTool.retrieve());
80 ATH_CHECK(m_trackExtensionTool.retrieve(EnableTool{m_doHoughConstants && m_doSecondStage}));
81 ATH_CHECK(m_trackFitterTool_1st.retrieve(EnableTool{m_doHoughConstants && m_doSecondStage}));
82 ATH_CHECK(m_overlapRemovalTool.retrieve(EnableTool{m_doHoughConstants && m_doSecondStage}));
83
84
85
87 if (m_ideal_geom == 0) {
88 ATH_MSG_INFO("Hough constants method needs idealized geometry > 0, aborting.");
89 return StatusCode::FAILURE;
90 }
91 m_nRegions = m_FPGATrackSimMapping->RegionMap_1st()->getNRegions();
92 m_pmap_2nd = m_FPGATrackSimMapping->PlaneMap_2nd(0);
93 m_pmap_1st = m_FPGATrackSimMapping->PlaneMap_1st(0);
94 // Get detector configurations
95 m_nLayers_1st = m_FPGATrackSimMapping->PlaneMap_1st(0)->getNLogiLayers();
96 m_nDim_1st = m_FPGATrackSimMapping->PlaneMap_1st(0)->getNCoords();
97 m_nLayers_2nd = m_FPGATrackSimMapping->PlaneMap_2nd(0)->getNLogiLayers();
98 m_nDim_2nd = m_FPGATrackSimMapping->PlaneMap_2nd(0)->getNCoords();
99 }
100 else {
101 // Get detector configurations
102 m_nLayers_1st = m_FPGATrackSimMapping->PlaneMap_2nd(0)->getNLogiLayers();
103 m_nRegions = m_FPGATrackSimMapping->RegionMap_2nd()->getNRegions();
104 m_nDim_1st = m_FPGATrackSimMapping->PlaneMap_2nd(0)->getNCoords();
105 }
106
107 m_sector_cum.resize(m_nRegions);
108
109 // Retrieve slice information
110 m_sliceMin = m_EvtSel->getMin();
111 m_sliceMax = m_EvtSel->getMax();
112
113 // Check q/pt binning information
114 if (m_qOverPtBins.size() == 0) {
115 ATH_MSG_ERROR("q/pt bin information not set in matrix element job options!");
116 return StatusCode::FAILURE;
117 }
118
119
120 // Histograms
122
124
125 return StatusCode::SUCCESS;
126}
127
128
130{
131 // Training tracks
132 for (unsigned i = 0; i < FPGATrackSimTrackPars::NPARS; i++) {
133 std::string name = "h_trainingTrack_" + FPGATrackSimTrackPars::parName(i);
134 std::string title = FPGATrackSimTrackPars::parName(i) + " of tracks passing pt/barcode check";
135
136 m_h_trainingTrack[i] = new TH1I(name.c_str(), title.c_str(), 100, m_sliceMin[i], m_sliceMax[i]);
137 ATH_CHECK(m_tHistSvc->regHist("/TRIGFPGATrackSimMATRIXOUT/" + name, m_h_trainingTrack[i]));
138 }
139
140 // Sector pars
141 for (unsigned i = 0; i < FPGATrackSimTrackPars::NPARS; i++) {
142
143 std::string name = "h_sectorPars_" + FPGATrackSimTrackPars::parName(i);
144 std::string title = "Average " + FPGATrackSimTrackPars::parName(i) + " in sector";
145
146 m_h_sectorPars[i] = new TH1I(name.c_str(), title.c_str(), 100, m_sliceMin[i], m_sliceMax[i]);
147 ATH_CHECK(m_tHistSvc->regHist("/TRIGFPGATrackSimMATRIXOUT/" + name, m_h_sectorPars[i]));
148 }
149
150 // Select hit failure
151 for (unsigned i = 0; i < FPGATrackSimTrackPars::NPARS; i++) {
152
153 std::string name = "h_SHfailure_" + FPGATrackSimTrackPars::parName(i);
154 std::string title = FPGATrackSimTrackPars::parName(i) + " of tracks failing in selectHit()";
155
156 m_h_SHfailure[i] = new TH1I(name.c_str(), title.c_str(), 100, m_sliceMin[i], m_sliceMax[i]);
157 ATH_CHECK(m_tHistSvc->regHist("/TRIGFPGATrackSimMATRIXOUT/" + name, m_h_SHfailure[i]));
158 }
159
160 // 3 hits in layer
161 for (unsigned i = 0; i < FPGATrackSimTrackPars::NPARS; i++) {
162
163 std::string name = "h_3hitsInLayer_" + FPGATrackSimTrackPars::parName(i);
164 std::string title = FPGATrackSimTrackPars::parName(i) + " of tracks containing 3+ hits in a single layer";
165
166 m_h_3hitsInLayer[i] = new TH1I(name.c_str(), title.c_str(), 100, m_sliceMin[i], m_sliceMax[i]);
167 ATH_CHECK(m_tHistSvc->regHist("/TRIGFPGATrackSimMATRIXOUT/" + name, m_h_3hitsInLayer[i]));
168 }
169
170 // Not enough hits
171 for (unsigned i = 0; i < FPGATrackSimTrackPars::NPARS; i++) {
172 std::string name = "h_notEnoughHits_" + FPGATrackSimTrackPars::parName(i);
173 std::string title = FPGATrackSimTrackPars::parName(i) + " of tracks failing because it didn't have enough hits";
174
175 m_h_notEnoughHits[i] = new TH1I(name.c_str(), title.c_str(), 100, m_sliceMin[i], m_sliceMax[i]);
176 ATH_CHECK(m_tHistSvc->regHist("/TRIGFPGATrackSimMATRIXOUT/" + name, m_h_notEnoughHits[i]));
177 }
178
179 m_h_trackQoP_okHits = new TH1I("h_trackQoP_okHits", "half inverse pt of tracks passing hit check",
180 m_nBins.qOverPt, m_sliceMin.qOverPt, m_sliceMax.qOverPt);
181 m_h_trackQoP_okRegion = new TH1I("h_trackQoP_okRegion", "half inverse pt of tracks passing region check",
182 m_nBins.qOverPt, m_sliceMin.qOverPt, m_sliceMax.qOverPt);
183 m_h_nHit = new TH1I("h_nHit", "number of hits in sector", 100, 0, 100);
184
185 ATH_CHECK(m_tHistSvc->regHist("/TRIGFPGATrackSimMATRIXOUT/h_trackQoP_okHits", m_h_trackQoP_okHits));
186 ATH_CHECK(m_tHistSvc->regHist("/TRIGFPGATrackSimMATRIXOUT/h_trackQoP_okRegion", m_h_trackQoP_okRegion));
187 ATH_CHECK(m_tHistSvc->regHist("/TRIGFPGATrackSimMATRIXOUT/h_nHit",m_h_nHit));
188
189 return StatusCode::SUCCESS;
190}
191
193{
194 FPGATrackSimTrackPars pars = track.getPars();
195 for (unsigned i = 0; i < FPGATrackSimTrackPars::NPARS; i++)
196 hists[i]->Fill(pars[i]);
197}
198
200// Execute
202
203
205{
206 ATH_MSG_DEBUG("execute()");
207 m_eventHeader->clearHits();
208 m_eventHeader->reset();
209 // Get hits and training tracks from this event
210 ATH_CHECK(m_hitInputTool->readData(m_eventHeader, Gaudi::Hive::currentContext()));
211
212 std::vector<FPGATrackSimHit> hits = getLogicalHits();
213
214 std::vector<FPGATrackSimTruthTrack> truth_tracks = m_eventHeader->optional().getTruthTracks();
215 std::vector<FPGATrackSimTruthTrack> tracks = filterTrainingTracks(truth_tracks);
216 m_nTracks += truth_tracks.size();
217 if (tracks.empty()) {
218 ATH_MSG_DEBUG("Empty training tracks");
219 return StatusCode::SUCCESS;
220 }
221 // Prepare a map of the hits according the barcode
222 std::map<int, std::vector<FPGATrackSimHit>> barcode_hits = makeBarcodeMap(hits, tracks);
223 // For each training track, find the sector it belongs to and accumulate the
224 // hit coordinates and track parameters.
225 for (FPGATrackSimTruthTrack const & track : tracks) {
226
227 int nSlices = m_FPGATrackSimMapping->SubRegionMap()->getNRegions();
228
229 // Get list of hits associated to the current truth track
230 std::vector<FPGATrackSimHit> & sector_hits = barcode_hits[track.getBarcode()];
231
232 const FPGATrackSimPlaneMap *t_pmap = nullptr;
233
234 // Get the hits that will form the actual sector
235
236 for (int iSlice = 0; iSlice<nSlices; iSlice++){
237 t_pmap = m_FPGATrackSimMapping->PlaneMap_2nd(iSlice);
238
239 for (auto & iHit : sector_hits) {
240 t_pmap->map(iHit);
241 }
242
243 /* For now, don't do this. If we need regionalized/binned fit constants it needs to come from the road.
244 std::vector<FPGATrackSimHit> sector_hits;
245 bool success = filterSectorHits(track_hits, sector_hits, track, true, iSlice);
246 if (!success) continue; // Skip this track if it has bad hits (not complete, etc.)
247 */
248
249 m_h_trackQoP_okHits->Fill(track.getQOverPt());
250
251 // Get the region of this sector
252 // TODO: do we need this the pattern recognition should deal with it.
253 int region = 0; //sgetRegion(sector_hits, false);
254 //if (region < 0 || region >= m_nRegions) continue;
255 m_h_trackQoP_okRegion->Fill(track.getQOverPt());
256
257 //For the Hough constants, find the Hough roads
258 std::vector<FPGATrackSimRoad> houghRoads;
260
261 std::vector<std::shared_ptr<const FPGATrackSimHit>> phits;
262
263 ATH_MSG_DEBUG("Starting from some number of sector hits = " << sector_hits.size());
264 for (const FPGATrackSimHit& hit : sector_hits) if (hit.isMapped() && hit.isReal()) phits.emplace_back(std::make_shared<const FPGATrackSimHit>(hit));
265 ATH_MSG_DEBUG("Passing nhits = " << phits.size() << " to road finder");
266 StatusCode sc = m_roadFinderTool->getRoads(phits, houghRoads, truth_tracks);
267 if (sc.isFailure()) ATH_MSG_WARNING("Hough Transform -> getRoads() failed");
268
269 ATH_MSG_DEBUG("We found " << houghRoads.size() << " roads");
270
271 // We now want to just form the accumulator for any valid combination of hits
272 // In first stage mode we'll make the track fitter just generate combinations
273 std::vector<FPGATrackSimTrack> tracks_1st;
274 if (m_doSecondStage) {
275 ATH_CHECK(m_trackFitterTool_1st->getTracks(houghRoads, tracks_1st, m_EvtSel->getMin(), m_EvtSel->getMax()));
276 ATH_CHECK(m_overlapRemovalTool->runOverlapRemoval(tracks_1st));
277 } else {
278 roadsToTrack(houghRoads, tracks_1st, m_pmap_1st);
279 ATH_MSG_DEBUG("We found " << tracks_1st.size() << " combinations");
280 }
281 for (const auto& track_comb : tracks_1st) {
282 std::vector<FPGATrackSimHit> track_hits = track_comb.getFPGATrackSimHits();
283
284 if (m_doSecondStage) { // if doing 2nd stage, we want to get tracks from the road and then do tracking and overlap removal
285
286 // Prepare the accumulator struct
287 std::vector<module_t> modules(m_nLayers_2nd);
289 std::vector<std::shared_ptr<const FPGATrackSimHit>> phits_2nd;
290
291 // Pass all hits-- it's not possible to only select second stage hits here...
292 for (const auto& hit : sector_hits) {
293 phits_2nd.push_back(std::make_shared<const FPGATrackSimHit>(hit));
294 }
295
296 // Use the track extension tool to actually produce a new set of roads.
297 std::vector<FPGATrackSimRoad> roads_2nd;
298 ATH_CHECK(m_trackExtensionTool->extendTracks(phits_2nd, tracks_1st, roads_2nd));
299
300 // Now produce "track" candidates and loop over them.
301 std::vector<FPGATrackSimTrack> tracks_2nd;
302 roadsToTrack(roads_2nd, tracks_2nd, m_pmap_2nd);
303 for (const FPGATrackSimTrack& track_2nd : tracks_2nd) {
304 std::vector<FPGATrackSimHit> track_hits_2nd = track_2nd.getFPGATrackSimHits();
305 std::vector<module_t> modules(m_nLayers_2nd);
307 acc.pars.qOverPt = track_2nd.getHoughY();
308 acc.pars.phi = track_2nd.getHoughX();
309
310 std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> modules_acc = {modules, acc};
311 std::vector<std::shared_ptr<const FPGATrackSimHit>> phits;
312 ATH_CHECK(makeAccumulator(track_hits_2nd, track, modules_acc));
313
314 // Add the track to the accumulate map
315 accumulate(m_sector_cum[region], modules_acc.first, modules_acc.second);
316
318 ATH_CHECK(fillAccumulatorByDropping(track_hits_2nd, false, acc.pars.phi, acc.pars.qOverPt, modules, m_sector_cum[region], track, iSlice));
319
321 }
322 }
323 else {
324 // For each track combination (from a Hough road)
325 double y = track_comb.getHoughY();
326 double x = track_comb.getHoughX();
327 // Prepare the accumulator struct
328 std::vector<module_t> modules(m_nLayers_1st);
330 acc.pars.qOverPt = y;
331 acc.pars.phi = x;
332 std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> modules_acc = {modules, acc};
333 ATH_CHECK(makeAccumulator(track_hits, track, modules_acc));
334
335 // Add the track to the accumulate map
336 accumulate(m_sector_cum[region], modules_acc.first, modules_acc.second);
337
339 ATH_CHECK(fillAccumulatorByDropping(track_hits, true, acc.pars.phi, acc.pars.qOverPt, modules, m_sector_cum[region], track, iSlice));
340
342 }
343 }
344 }
345 else{
346 // Prepare the accumulator struct
347 std::vector<module_t> modules(m_nLayers_1st);
349 std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> modules_acc = {modules, acc};
350 ATH_CHECK(makeAccumulator(sector_hits, track, modules_acc));
351
352 // Add the track to the accumulate map
353 accumulate(m_sector_cum[region], modules_acc.first, modules_acc.second);
354
356 ATH_CHECK(fillAccumulatorByDropping(sector_hits, true, acc.pars.phi, acc.pars.qOverPt, modules, m_sector_cum[region], track, iSlice));
357
359 }
360 }
361 }
362
363 return StatusCode::SUCCESS;
364}
365
366
367// Converts raw hits from header into logical hits, and filters those in FPGATrackSim layers
368// Could replace this with the RawToLogical tool (but probably won't)
369std::vector<FPGATrackSimHit> FPGATrackSimMatrixGenAlgo::getLogicalHits()
370{
371 std::vector<FPGATrackSimHit> hits;
372 //Setup the logical header...
374 //Map the hits to the logical header...
375 unsigned stage = 0;
376 if (m_doHoughConstants) stage = 1; // For now Hough constants only works on 1st stage
377 else stage = 2;
378 StatusCode sc = m_hitMapTool->convert(stage, *m_eventHeader, logicalHeader);
379 if (sc.isFailure()) ATH_MSG_ERROR("Hit mapping failed");
380
381 // Since the clustering tool modifies the logical towers-- refactored this
382 // to only access the output hits from the towers.
383 if (m_doClustering) {
384 std::vector<FPGATrackSimCluster> clustered_hits;
385 sc = m_clusteringTool->DoClustering(logicalHeader, clustered_hits);
386 if (sc.isFailure()) ATH_MSG_ERROR("Clustering failed");
387 }
388 // Optionally do spacepoints (as well).
389 if (m_doSpacePoints) {
390 std::vector<FPGATrackSimCluster> spacepoints;
391 sc = m_spacePointsTool->DoSpacePoints(logicalHeader, spacepoints);
392 if (sc.isFailure()) ATH_MSG_ERROR("Spacepoints failed");
393 }
394
395 // It should now be safe to pull the towers, regardless.
396 std::vector<FPGATrackSimTowerInputHeader> towers = logicalHeader.towers();
397 for (auto &tower : towers) {
398 std::vector<FPGATrackSimHit> const & towerHits = tower.hits();
399 for (FPGATrackSimHit const & hit : towerHits) {
400 hits.push_back(hit);
401 }
402 }
403 return hits;
404}
405
406
407// Filters tracks based on m_PT_THRESHOLD and m_TRAING_PDG and D0_THRESHOLD
408std::vector<FPGATrackSimTruthTrack> FPGATrackSimMatrixGenAlgo::filterTrainingTracks(std::vector<FPGATrackSimTruthTrack> const & truth_tracks) const
409{
410 std::vector<FPGATrackSimTruthTrack> training_tracks;
411
412 for (FPGATrackSimTruthTrack const & track : truth_tracks) {
413 if (HepMC::generations(&track) >= 1 || std::abs(track.getPDGCode()) != m_TRAIN_PDG) continue;
414 if (std::abs(track.getD0()) > m_D0_THRESHOLD) continue;
415
416 // Actually use the event selection service here to kill anything outside the region.
417 if (!(m_EvtSel->passMatching(track))) continue;
418
419 double pt = TMath::Sqrt(track.getPX()*track.getPX() + track.getPY()*track.getPY());
420 double pt_GeV = pt / 1000;
421
422 // Add the track to the list of good tracks
423 if (pt_GeV > m_PT_THRESHOLD) training_tracks.push_back(track);
424
425 // Debug
426 if (msgLvl(MSG::DEBUG)) {
427 double c = track.getQ() /(2 * pt);
428 double eta = TMath::ASinH(track.getPZ() / pt);
429 double phi = TMath::ATan2(track.getPY(), track.getPX());
430 ATH_MSG_DEBUG("pt_GeV = "<< pt_GeV
431 << " c = " << c
432 << " eta = " << eta
433 << " phi = " << phi
434 << " pdgcode = " << track.getPDGCode());
435 }
437 }
438
439 return training_tracks;
440}
441
442
443// Sorts 'hits' by barcodes appearing in 'tracks', drops the rest.
444std::map<int, std::vector<FPGATrackSimHit>> FPGATrackSimMatrixGenAlgo::makeBarcodeMap(std::vector<FPGATrackSimHit> const & hits, std::vector<FPGATrackSimTruthTrack> const & tracks) const
445{
446 std::map<int, std::vector<FPGATrackSimHit>> map;
447
448 // Ready the barcodes
449 for (const FPGATrackSimTruthTrack & track : tracks)
450 map[track.getBarcode()] = std::vector<FPGATrackSimHit>();
451
452 // Add the hits
453 for (const FPGATrackSimHit & hit : hits) {
454 // Get the predominant barcode for the current hit
455 int barcode = hit.getTruth().best_barcode();
456
457 // Add hit to the list; skip the hits if not associated to a good truth tracks
458 auto it = map.find(barcode);
459 if (it != map.end()) (*it).second.push_back(hit);
460 }
461
462 return map;
463}
464
465
466// Given two hits in the same layer, selects the better hit to use for sector
467// generation based on multiple criteria.
468//
469// Returns:
470// 0 - Failure, this track should be discarded
471// 1 - Keep old hit
472// 2 - Use new hit
473//
474// NB: sector overlap is a perfectly reasonable situation with forward disks
475// eta and phi will differ in general in this case
476// Take the lower-z hit preferentially (right thing to do? d0/pT tradeoff)
477// But something fishy is going on if we've got two hits on the same disk.
479{
480 if (old_hit.isReal() && !new_hit.isReal()) return selectHit_returnCode::SH_KEEP_OLD;
481 if (!old_hit.isReal() && new_hit.isReal()) return selectHit_returnCode::SH_KEEP_NEW;
482 if (!old_hit.isReal() && !new_hit.isReal()) return selectHit_returnCode::SH_FAILURE;
483 if ((new_hit.getSection() == old_hit.getSection()) && (new_hit.getLayer() == old_hit.getLayer())
484 && (new_hit.getEtaModule() == old_hit.getEtaModule()) && (new_hit.getPhiModule() == old_hit.getPhiModule())) {
485 ATH_MSG_DEBUG("Two hits on same module");
487 }
488 // Always prefer spacepoints, regardless of all other considerations.
489 // This is necessary in part due to spacepoint duplication.
490 if (old_hit.getHitType() == HitType::spacepoint && new_hit.getHitType() != HitType::spacepoint) {
492 } else if (old_hit.getHitType() != HitType::spacepoint && new_hit.getHitType() == HitType::spacepoint) {
494 }
495 int new_section = new_hit.getSection();
496 int old_section = old_hit.getSection();
497
498 if (old_section == new_section) {
499 if (old_hit.getEtaModule() == new_hit.getEtaModule()) {
500 int rmax = 0;
501 if (m_doHoughConstants && is1ststage) {
502 int phi_max = m_FPGATrackSimMapping->SubRegionMap()->getRegionBoundaries(subregion, new_hit.getLayer(), new_section).phi_max;
503 int phi_min = m_FPGATrackSimMapping->SubRegionMap()->getRegionBoundaries(subregion, new_hit.getLayer(), new_section).phi_min;
504 rmax = phi_max - phi_min;
505
506 }
507 else {
508 int phi_max = m_FPGATrackSimMapping->SubRegionMap_2nd()->getRegionBoundaries(subregion, new_hit.getLayer(), new_section).phi_max;
509 int phi_min = m_FPGATrackSimMapping->SubRegionMap_2nd()->getRegionBoundaries(subregion, new_hit.getLayer(), new_section).phi_min;
510 rmax = phi_max - phi_min;
511 }
512
513 int phi_diff = old_hit.getPhiModule() - new_hit.getPhiModule();
514
515 if (phi_diff == 1 || phi_diff == -rmax) return selectHit_returnCode::SH_KEEP_OLD;
516 else if (phi_diff == -1 || phi_diff == rmax) return selectHit_returnCode::SH_KEEP_NEW;
517 else {
518 ATH_MSG_DEBUG("Hits are too far away in phi");
520 }
521 }
522 else { // Different eta is no good
523 ATH_MSG_DEBUG("Hits are in different eta");
525 }
526 }
527 else { // sections are different
528 int layer = old_hit.getLayer();
529 bool old_isEC = 0;
530 bool new_isEC = 0;
531 int old_disk = 0;
532 int new_disk = 0;
533 if (m_doHoughConstants && is1ststage) {
534 old_isEC = m_FPGATrackSimMapping->PlaneMap_1st(subregion)->isEC(layer, old_section);
535 new_isEC = m_FPGATrackSimMapping->PlaneMap_1st(subregion)->isEC(layer, new_section);
536 old_disk = m_FPGATrackSimMapping->PlaneMap_1st(subregion)->getLayerInfo(layer, old_section).physDisk;
537 new_disk = m_FPGATrackSimMapping->PlaneMap_1st(subregion)->getLayerInfo(layer, new_section).physDisk;
538 }
539 else {
540 old_isEC = m_FPGATrackSimMapping->PlaneMap_2nd(subregion)->isEC(layer, old_section);
541 new_isEC = m_FPGATrackSimMapping->PlaneMap_2nd(subregion)->isEC(layer, new_section);
542 old_disk = m_FPGATrackSimMapping->PlaneMap_2nd(subregion)->getLayerInfo(layer, old_section).physDisk;
543 new_disk = m_FPGATrackSimMapping->PlaneMap_2nd(subregion)->getLayerInfo(layer, new_section).physDisk;
544 }
545 // If one is barrel and one endcap, it's definitely OK, take the barrel hit
546 if (old_isEC != new_isEC) {
547
548 if (old_isEC) return selectHit_returnCode::SH_KEEP_NEW;
550 }
551 // Two endcap hits : same disk: discard
552 else if (old_disk == new_disk) {
553
554 ATH_MSG_DEBUG("Two modules hit in same physical disk " << old_disk);
556 }
557 // Two endcap hits on same side: different disks: take the lower-z
558 else {
559 ATH_MSG_DEBUG("Keeping the lower-z of the two disks (" << old_disk << ", " << new_disk << ") hit");
560 if (old_disk > new_disk) return selectHit_returnCode::SH_KEEP_NEW;
562 }
563 }
564}
565
566
567// A sector is created from hits in all layers. Sometimes there will be extraneous hits
568// that need to be filtered. This functions returns true on success, and by reference
569// the filtered hit list with size m_nLayers_1st.
570//
571// See selectHit() for details on which hit is chosen when there's more than 1 per layer.
572bool FPGATrackSimMatrixGenAlgo::filterSectorHits(std::vector<FPGATrackSimHit> const & all_hits, std::vector<FPGATrackSimHit> & sector_hits,
573 FPGATrackSimTruthTrack const & t, bool is1ststage, int subregion) const
574{
575 FPGATrackSimHit nohit;
577 int nLayers = (is1ststage ? m_nLayers_1st : m_nLayers_2nd);
578 const FPGATrackSimRegionMap *rmap = (is1ststage ? m_FPGATrackSimMapping->SubRegionMap() : m_FPGATrackSimMapping->SubRegionMap_2nd());
579 sector_hits.resize(nLayers, nohit);
580 std::vector<int> layer_count(nLayers); // count number of hits seen in each layer
581
582 for (FPGATrackSimHit const & hit : all_hits) {
583 if (!hit.isReal() || !hit.isMapped()) continue;
584
585 // Sanity check. make sure the hit is actually in the first stage?
586 // If the hit falls within the boundaries of ANY subregion in the first stage, it's 1st stage.
587 if (rmap->getRegions(hit).size() == 0) {
588 continue;
589 }
590 int layer = hit.getLayer();
591 if (layer_count[layer] == 0){
592 layer_count[layer]++;
593 sector_hits[layer] = hit;
594 }
595 else if (layer_count[layer] == 1) {
596 layer_count[layer]++;
597 // Already found a hit in this layer, so pick which hit to use
598 selectHit_returnCode selected_hit = selectHit(sector_hits[layer], hit, is1ststage, subregion);
599
600 if (selected_hit == selectHit_returnCode::SH_FAILURE) {
602 return false;
603 }
604 else if (selected_hit == selectHit_returnCode::SH_KEEP_NEW) sector_hits[layer] = hit;
605 }
606 else {
607 ATH_MSG_DEBUG("Too many hits on a plane, exiting filterHitsSec");
609 return false;
610 }
611 }
612 // Count number of wildcards, spacepoints, and pixel hits.
613 int nwc = 0;
614 int num_sp = 0;
615 int num_pixel = 0;
616
617 // Check we have the right number of hits.
618 for (int i = 0; i < nLayers; ++i)
619 {
620 if (layer_count[i] == 0)
621 {
622 ATH_MSG_DEBUG("Layer " << i << " has no hits");
623 nwc++;
624 }
625
626 // Now that we've decided which hit to use-- check their type.
627 if (sector_hits[i].getHitType() == HitType::spacepoint) {
628 num_sp += 1;
629 }
630 if (sector_hits[i].isPixel()) {
631 num_pixel += 1;
632 }
633 }
634 ATH_MSG_DEBUG("Found " << nwc << " wildcards compared to maximum: " << m_MaxWC);
635 // Divide by 2 due to spacepoint duplication.
636 num_sp /= 2;
637 ATH_MSG_DEBUG("Found " << num_sp << " spacepoints after removing duplicates.");
638 // Require we don't have too many wildcards.
639 if (nwc > m_MaxWC)
640 {
642 return false;
643 }
644 // Require that we have a certain number of "2D" hits (i.e. pixels and spacepoints)
645 // The effect of this is that we can ensure we have 4/5 2D hits but 7/9 hits total.
646 // NOTE Again, uncomment logic below for second stage running.
647 num_sp += num_pixel;
648 int minSpacePlusPixel = /*m_isSecondStage ? m_minSpacePlusPixel2 :*/ m_minSpacePlusPixel;
649 if (num_sp < minSpacePlusPixel) {
650 ATH_MSG_DEBUG("Not enough pixel hits + spacepoints (" << num_sp << " < " << minSpacePlusPixel << ")");
652 return false;
653 }
654 return true;
655}
656
657
658// Returns the lowest index region that contains all hits in 'hits'
659int FPGATrackSimMatrixGenAlgo::getRegion(std::vector<FPGATrackSimHit> const & hits, bool is1ststage) const
660{
661 // Start with a bitmask, all true, and set a region to false if any mismatch is found
662 std::vector<bool> region_mask(m_nRegions, true);
663
664 for (FPGATrackSimHit const & hit : hits) {
665 if (hit.isReal()) { // don't worry about hits that are WCs
666 for (int region = 0; region < m_nRegions; region++) {
667 if (m_doHoughConstants && is1ststage) {
668 if (!m_FPGATrackSimMapping->RegionMap_1st()->isInRegion(region, hit))
669 region_mask[region] = false;
670 }
671 else {
672 if (!m_FPGATrackSimMapping->RegionMap_2nd()->isInRegion(region, hit))
673 region_mask[region] = false;
674 }
675 }
676 }
677 }
678
679 // For now just give preference to lowest region index for simplicity
680 for (int region = 0; region < m_nRegions; region++) {
681 if (region_mask[region])
682 return region;
683 }
684
685 return -1;
686}
687
688// Fill accumulators by dropping one hit
689StatusCode FPGATrackSimMatrixGenAlgo::fillAccumulatorByDropping(std::vector<FPGATrackSimHit> &sector_hits, bool is1ststage, double x, double y, std::vector<module_t> &modules, AccumulateMap &map, FPGATrackSimTruthTrack const & track, int subregion) const
690{
691
692 int nLayers = (is1ststage ? m_nLayers_1st : m_nLayers_2nd);
693 int nDim = (is1ststage ? m_nDim_1st : m_nDim_2nd);
694
695 int nwc = 0;
696 for (auto module : modules) {
697 if (module == -1) nwc++;
698 }
699 // Don't do this unless we miss at most one hit!
700 if (nwc < m_MaxWC) {
701 for (int layer = 0; layer < nLayers; layer++) {
702 // Back up the current hit in this layer.
703 FPGATrackSimHit backup_hit = sector_hits[layer];
704
705 // Create a new wildcard hit, and put it here.
706 ATH_MSG_DEBUG("Attempting to make wildcard in layer " << layer << ", is1ststage = " << is1ststage);
707 FPGATrackSimHit *wcHit = new FPGATrackSimHit();
709 wcHit->setLayer(layer);
710 if (is1ststage) wcHit->setDetType(m_FPGATrackSimMapping->PlaneMap_1st(subregion)->getDetType(layer));
711 else wcHit->setDetType(m_FPGATrackSimMapping->PlaneMap_2nd(subregion)->getDetType(layer));
712
713 sector_hits[layer] = *wcHit;
714
715 // If this is a spacepoint, we must also convert the other hit.
716 FPGATrackSimHit other_backup = backup_hit;
717 unsigned other_layer = 0;
718 if (backup_hit.getHitType() == HitType::spacepoint) {
719 other_layer = (backup_hit.getPhysLayer() % 2 == 0) ? layer + 1 : layer - 1;
720 other_backup = sector_hits[other_layer];
721 sector_hits[other_layer] = other_backup.getOriginalHit();
722 }
723
724 FPGATrackSimMatrixAccumulator new_acc(nLayers, nDim);
725 new_acc.pars.qOverPt = y;
726 new_acc.pars.phi = x;
727 std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> new_modules_acc = {modules, new_acc};
728
729 auto sc = makeAccumulator(sector_hits, track, new_modules_acc);
730 if (sc != StatusCode::SUCCESS){
731 delete wcHit;
732 ATH_MSG_ERROR("FPGATrackSimMatrixGenAlgo::fillAccumulatorByDropping; makeAccumulator failed");
733 return StatusCode::FAILURE;
734 }
735 accumulate(map, new_modules_acc.first, new_modules_acc.second);
736
737 // Restore the hit. May not be necessary to clean up wcHit here.
738 sector_hits[layer] = backup_hit;
739 delete wcHit;
740
741 // Restore the other layer, if this is a spacepoint.
742 if (backup_hit.getHitType() == HitType::spacepoint) {
743 sector_hits[other_layer] = other_backup;
744 }
745 }
746 }
747 return StatusCode::SUCCESS;
748}
749
750// Given a track and corresponding hits, returns the sector (list of modules) and the accumulation
751// struct.
752StatusCode FPGATrackSimMatrixGenAlgo::makeAccumulator(std::vector<FPGATrackSimHit> const & sector_hits, FPGATrackSimTruthTrack const & track, std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> & accumulator) const
753{
754
755
757 int nLayers = (m_doSecondStage ? m_nLayers_2nd : m_nLayers_1st);
758 int nDim = (m_doSecondStage ? m_nDim_2nd : m_nDim_1st);
759 std::vector<module_t> modules(nLayers);
760 FPGATrackSimMatrixAccumulator acc(nLayers, nDim);
761
762 //find the bin!
763 // NOTE: this only implements q/pt binning, not the subregion / eta pattern-based constants for now.
764 int sectorbin = 0;
765 double qoverpt = track.getQ() / track.getPt();
766
767 // for 2nd stage we only use one q/pt bin
768 if (m_absQOverPtBinning || m_doSecondStage) qoverpt = abs(qoverpt);
769 if (!m_doSecondStage) {
770 for (unsigned bin = 0; bin < m_qOverPtBins.size()-1; bin++) {
772 if (qoverpt < m_qOverPtBins[bin+1]) break;
773 }
774 }
775
776 // Create sector definitions (list of modules)
777 std::string module_printout = "";
778 for (int i = 0; i < nLayers; i++)
779 {
780 if (sector_hits[i].isReal()) {
781 if (m_single) modules[i] = sector_hits[i].getIdentifierHash();
782 else {
783 modules[i] = sectorbin;
784 // Modify sectorbin by a "type" field, which for now means: 0 = not spacepoint, 1 = spacepoint.
785 // This will fail if we have more than 99 q/pt bins!
786 if (sector_hits[i].getHitType() == HitType::spacepoint) {
788 }
789 module_printout += std::to_string(modules[i]) + ", ";
790 }
791 }
792 else {
793 modules[i] = -1; // WC
794 }
795 }
796
797 ATH_MSG_DEBUG("Generating track in sectorbin = " << sectorbin << " with modules: " << module_printout);
798
799
800 if (m_single) {
801 const int ToKeep[13] = {2200,2564,2861,3831,5368,14169,14173,20442,20446,29625,29629,42176,42180};
802 bool keepThis = true;
803 for (int i = 0; i < 13; i++) {
804 if (modules[i] != ToKeep[i] && modules[i] != -1) {
805 keepThis = false;
806 }
807 }
808
809 if (!keepThis) {
810 for (int i = 0; i < 13; i++) modules[i] = -1;
811 }
812 else {
813 for (int i = 0; i < 13; i++) {
814 }
815 }
816 }
817
818
819 // Hough Constants parameters
820 double y = accumulator.second.pars.qOverPt;
821 double x = accumulator.second.pars.phi;
822
823 // Vectorize (flatten) coordinates
824 std::vector<float> coords;
825
826 for (int i = 0; i < nLayers; ++i) {
827
828 if (sector_hits[i].isReal()) {
829 double target_r = (m_doSecondStage ? m_FPGATrackSimMapping->RegionMap_2nd()->getAvgRadius(0, i) : m_FPGATrackSimMapping->RegionMap_1st()->getAvgRadius(0, i));
830 // If this is a spacepoint the target R should be the average of the two layers.
831 // TODO, get this to be loaded in from a mean radii file into the mapping infrastructure.
832 if (sector_hits[i].getHitType() == HitType::spacepoint) {
833 int other_layer = (sector_hits[i].getSide() == 0) ? i + 1 : i - 1;
834 target_r = (m_doSecondStage ?
835 (target_r + m_FPGATrackSimMapping->RegionMap_2nd()->getAvgRadius(0, other_layer))/2. :
836 (target_r + m_FPGATrackSimMapping->RegionMap_1st()->getAvgRadius(0, other_layer))/2.);
837 }
838
839 std::vector<float> coords_tmp;
840 if ( m_ideal_geom > 1 ) {
841 coords_tmp = computeIdealCoords(sector_hits[i], x, y, target_r, m_doDeltaPhiConsts, TrackCorrType::Second);
842 }
843 else {
844 coords_tmp = computeIdealCoords(sector_hits[i], x, y, target_r, m_doDeltaPhiConsts, TrackCorrType::None);
845 }
846
847 // Create phi for any hits that are not spacepoints, as well as "inner" spacepoints.
848 // but not outer spacepoints. this avoids duplicate coordinates.
849 if (sector_hits[i].getHitType() != HitType::spacepoint || sector_hits[i].getSide() == 0) {
850 // get idealized gPhi
851 coords.push_back(coords_tmp[1]);
852 }
853
854 // Create a z coordinate for the "outer" layer of the spacepoint and for 2D pixel hits.
855 // This means that a spacepoint will write out (phi, eta) pairs, but (0, phi) or (phi, 0) if it's missing.
856 if (sector_hits[i].getDim() == 2 || (sector_hits[i].getHitType() == HitType::spacepoint && (sector_hits[i].getPhysLayer() % 2) == 1)) {
857 // get idealized z
858 coords.push_back(coords_tmp[0]);
859 }
860 }
861 else {
862 if (pmap->getDim(i) == 2) {
863 coords.push_back(0);
864 }
865 coords.push_back(0);
866 }
867 }
868
869 assert(coords.size() == (size_t)nDim);
870 acc.hit_coords = coords;
871 acc.hit_coordsG = coords;
872
873 // Get the track parameters
874 acc.pars = track.getPars();
876 acc.pars.qOverPt = (y / 1000.0) - track.getQOverPt(); // fit for delta q/pT
877 acc.pars.phi = x - track.getPhi(); // fit for delta phi_0
878 }
879
881 for (unsigned i = 0; i < FPGATrackSimTrackPars::NPARS; i++)
882 bins[i] = (acc.pars[i] - m_sliceMin[i]) * m_nBins[i] / (m_sliceMax[i] - m_sliceMin[i]);
883 acc.track_bins.push_back(bins);
884
885 // Force phi to be in [0, 2pi] (post binning)
886 if (!m_doDeltaPhiConsts) {
887 while (acc.pars.phi < 0) acc.pars.phi += 2*M_PI;
888 while (acc.pars.phi > 2*M_PI) acc.pars.phi -= 2*M_PI;
889 }
890
891 // Calculate the pre-multiplied elements
892 for (int i = 0; i < nDim; i++)
893 {
894 acc.hit_x_QoP[i] = coords[i] * acc.pars.qOverPt;
895 acc.hit_xG_HIP[i] = coords[i] * acc.pars.qOverPt;
896 acc.hit_x_d0[i] = coords[i] * acc.pars.d0;
897 acc.hit_x_z0[i] = coords[i] * acc.pars.z0;
898 acc.hit_x_eta[i] = coords[i] * acc.pars.eta;
899 acc.hit_xG_eta[i] = coords[i] * acc.pars.eta;
900 acc.hit_x_phi[i] = coords[i] * acc.pars.phi;
901
902 for (int j = i; j < nDim; j++)
903 acc.covariance[i * nDim + j] = coords[i] * coords[j];
904
905 for (int j = i; j < nDim; j++)
906 acc.covarianceG[i * nDim + j] = coords[i] * coords[j];
907 }
908
909 accumulator = {modules, acc};
910 return StatusCode::SUCCESS;
911}
912
913
914
916// Finalize
918
919
921{
922 ATH_MSG_DEBUG("finalize()");
923 ATH_MSG_INFO("Tracks used: " << m_nTracksUsed << "/" << m_nTracks);
924 int nLayers = (m_doSecondStage ? m_nLayers_2nd : m_nLayers_1st);
925 int nDim = (m_doSecondStage ? m_nDim_2nd : m_nDim_1st);
926
927 for (int region = 0; region < m_nRegions; region++) {
928 // Create the tree
929 std::stringstream name;
930 std::stringstream title;
931 name << "am" << region;
932 title << "Ambank " << region << " parameters";
933 TTree* tree = new TTree(name.str().c_str(), title.str().c_str());
934 ATH_CHECK(m_tHistSvc->regTree(Form("/TRIGFPGATrackSimMATRIXOUT/%s",tree->GetName()), tree));
935
936 // Fill the tree
937 ::fillTree(m_sector_cum[region], tree, nLayers, nDim);
938 // Monitoring
939 ATH_MSG_INFO("Sectors found in region " << region << ": " << m_sector_cum[region].size());
940 for (auto & sector_info : m_sector_cum[region]) {
941 double coverage = sector_info.second.track_bins.size();
942 m_h_nHit->Fill(coverage);
943 for (unsigned i = 0; i < FPGATrackSimTrackPars::NPARS; i++)
944 m_h_sectorPars[i]->Fill(sector_info.second.pars[i] / coverage);
945 }
946 }
947
949 ATH_CHECK(m_tHistSvc->finalize());
950 return StatusCode::SUCCESS;
951}
952
953
955{
956 TTree* sliceTree = new TTree("slice", "Region slice boundaries"); // slice
957
958 sliceTree->Branch("c_max", &m_sliceMax.qOverPt);
959 sliceTree->Branch("d0_max", &m_sliceMax.d0);
960 sliceTree->Branch("phi_max", &m_sliceMax.phi);
961 sliceTree->Branch("z0_max", &m_sliceMax.z0);
962 sliceTree->Branch("eta_max", &m_sliceMax.eta);
963
964 sliceTree->Branch("c_min", &m_sliceMin.qOverPt);
965 sliceTree->Branch("d0_min", &m_sliceMin.d0);
966 sliceTree->Branch("phi_min", &m_sliceMin.phi);
967 sliceTree->Branch("z0_min", &m_sliceMin.z0);
968 sliceTree->Branch("eta_min", &m_sliceMin.eta);
969
970 sliceTree->Branch("c_slices", &m_nBins.qOverPt);
971 sliceTree->Branch("d0_slices", &m_nBins.d0);
972 sliceTree->Branch("phi_slices", &m_nBins.phi);
973 sliceTree->Branch("z0_slices", &m_nBins.z0);
974 sliceTree->Branch("eta_slices", &m_nBins.eta);
975
976 StatusCode sc = m_tHistSvc->regTree("/TRIGFPGATrackSimMATRIXOUT/slice",sliceTree);
977 if (sc.isFailure()) ATH_MSG_ERROR("tHist failed");
978
979 sliceTree->Fill();
980}
#define M_PI
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::vector< float > computeIdealCoords(const FPGATrackSimHit &hit, const double hough_x, const double hough_y, const double target_r, const bool doDeltaGPhis, const TrackCorrType trackCorrType)
void roadsToTrack(std::vector< FPGATrackSimRoad > &roads, std::vector< FPGATrackSimTrack > &track_cands, const FPGATrackSimPlaneMap *pmap)
bool accumulate(AccumulateMap &map, std::vector< module_t > const &modules, FPGATrackSimMatrixAccumulator const &acc)
Accumulates an accumulator (e.g.
Helper struct for accumulating sector information for matrix generation.
std::unordered_map< std::vector< module_t >, FPGATrackSimMatrixAccumulator, container_hash< std::vector< module_t > > > AccumulateMap
void fillTrackPars(TH1I *const hists[FPGATrackSimTrackPars::NPARS], FPGATrackSimTruthTrack const &track)
Algorithm to generate matrix files, to be used for sector and constant generation.
void fillTree(AccumulateMap &map, TTree *tree, int nLayers, int nCoords)
Writes the contents of an AccumulateMap into the supplied tree (one entry per sector).
Stores slice definitions for FPGATrackSim regions.
static Double_t sc
static const std::vector< std::string > bins
#define y
#define x
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
bool msgLvl(const MSG::Level lvl) const
void setLayer(unsigned v)
void setHitType(HitType type)
int getEtaModule(bool old=false) const
unsigned getPhiModule() const
unsigned getPhysLayer(bool old=false) const
bool isReal() const
const FPGATrackSimHit getOriginalHit() const
unsigned getSection() const
HitType getHitType() const
void setDetType(SiliconTech detType)
const std::vector< FPGATrackSimTowerInputHeader > & towers() const
ToolHandle< FPGATrackSimRawToLogicalHitsTool > m_hitMapTool
std::map< int, std::vector< FPGATrackSimHit > > makeBarcodeMap(std::vector< FPGATrackSimHit > const &hits, std::vector< FPGATrackSimTruthTrack > const &tracks) const
Gaudi::Property< float > m_temp_c_max
FPGATrackSimMatrixGenAlgo(const std::string &name, ISvcLocator *pSvcLocator)
Gaudi::Property< bool > m_doDeltaPhiConsts
Gaudi::Property< float > m_temp_d0_max
const FPGATrackSimPlaneMap * m_pmap_2nd
std::vector< FPGATrackSimTruthTrack > filterTrainingTracks(std::vector< FPGATrackSimTruthTrack > const &truth_tracks) const
Gaudi::Property< std::vector< double > > m_qOverPtBins
Gaudi::Property< float > m_temp_phi_max
Gaudi::Property< int > m_temp_z0_slices
Gaudi::Property< float > m_PT_THRESHOLD
Gaudi::Property< int > m_temp_d0_slices
Gaudi::Property< int > m_temp_eta_slices
TH1I * m_h_trainingTrack[FPGATrackSimTrackPars::NPARS]
Gaudi::Property< int > m_temp_phi_slices
ToolHandle< FPGATrackSimRoadUnionTool > m_roadFinderTool
Gaudi::Property< float > m_temp_c_min
Gaudi::Property< float > m_temp_z0_max
Gaudi::Property< float > m_temp_eta_min
Gaudi::Property< float > m_D0_THRESHOLD
Gaudi::Property< bool > m_doSpacePoints
Gaudi::Property< bool > m_absQOverPtBinning
Gaudi::Property< float > m_temp_phi_min
Gaudi::Property< float > m_temp_z0_min
StatusCode makeAccumulator(std::vector< FPGATrackSimHit > const &sector_hits, FPGATrackSimTruthTrack const &track, std::pair< std::vector< module_t >, FPGATrackSimMatrixAccumulator > &accumulator) const
ToolHandle< FPGATrackSimClusteringToolI > m_clusteringTool
ToolHandle< FPGATrackSimOverlapRemovalTool > m_overlapRemovalTool
Gaudi::Property< bool > m_doClustering
TH1I * m_h_notEnoughHits[FPGATrackSimTrackPars::NPARS]
Gaudi::Property< int > m_minSpacePlusPixel
const FPGATrackSimPlaneMap * m_pmap_1st
TH1I * m_h_sectorPars[FPGATrackSimTrackPars::NPARS]
std::vector< FPGATrackSimHit > getLogicalHits()
TH1I * m_h_3hitsInLayer[FPGATrackSimTrackPars::NPARS]
FPGATrackSimEventInputHeader * m_eventHeader
ToolHandle< FPGATrackSimTrackFitterTool > m_trackFitterTool_1st
ServiceHandle< ITHistSvc > m_tHistSvc
selectHit_returnCode selectHit(FPGATrackSimHit const &old_hit, FPGATrackSimHit const &new_hit, bool is1ststage, int subregion) const
std::vector< AccumulateMap > m_sector_cum
StatusCode fillAccumulatorByDropping(std::vector< FPGATrackSimHit > &sector_hits, bool is1ststage, double x, double y, std::vector< module_t > &modules, AccumulateMap &map, FPGATrackSimTruthTrack const &track, int subregion) const
Gaudi::Property< float > m_temp_d0_min
Gaudi::Property< bool > m_dropHitsAndFill
Gaudi::Property< int > m_temp_c_slices
ToolHandle< IFPGATrackSimTrackExtensionTool > m_trackExtensionTool
ServiceHandle< IFPGATrackSimMappingSvc > m_FPGATrackSimMapping
Gaudi::Property< bool > m_doHoughConstants
ServiceHandle< IFPGATrackSimEventSelectionSvc > m_EvtSel
int getRegion(std::vector< FPGATrackSimHit > const &hits, bool is1ststage) const
bool filterSectorHits(std::vector< FPGATrackSimHit > const &all_hits, std::vector< FPGATrackSimHit > &sector_hits, FPGATrackSimTruthTrack const &t, bool is1ststage, int subregion) const
Gaudi::Property< float > m_temp_eta_max
TH1I * m_h_SHfailure[FPGATrackSimTrackPars::NPARS]
ToolHandle< FPGATrackSimSpacePointsToolI > m_spacePointsTool
Gaudi::Property< bool > m_doSecondStage
ToolHandle< IFPGATrackSimInputTool > m_hitInputTool
uint32_t getDim(size_t logiLayer) const
void map(FPGATrackSimHit &hit) const
static std::string parName(unsigned i)
STL class.
int generations(const T &p)
Method to return how many interactions a particle has undergone during simulation (TODO migrate to be...
constexpr int QPT_SECTOR_OFFSET
constexpr int SPACEPOINT_SECTOR_OFFSET
TChain * tree