ATLAS Offline Software
Loading...
Searching...
No Matches
FPGATrackSimTrack.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6
10#include <iostream>
11#include <iomanip>
12using namespace std;
13
14// first stage only
15
16// We need a destructor apparently?
18
19std::vector<float> FPGATrackSimTrack::getCoords(unsigned ilayer) const
20{
21 std::vector<float> coords;
22 if (ilayer >= m_hit_ptrs.size())
23 throw std::range_error("FPGATrackSimTrack::getCoords() out of bounds");
24 if (!m_hit_ptrs[ilayer])
25 throw std::range_error("FPGATrackSimTrack::getCoords() null pointer at index " + std::to_string(ilayer));
26
27 const auto& hit = *m_hit_ptrs[ilayer];
28
30 {
31 coords.push_back(hit.getEtaIndex());
32 coords.push_back(hit.getPhiIndex());
33 }
34 else
35 {
36 coords = computeIdealCoords(ilayer);
37 }
38
39 return coords;
40}
41
42std::vector<float> FPGATrackSimTrack::computeIdealCoords(unsigned ilayer) const
43{
44
45 double target_r = m_idealRadii[ilayer];
46 if (ilayer >= m_hit_ptrs.size() || !m_hit_ptrs[ilayer])
47 throw std::range_error("FPGATrackSimTrack::computeIdealCoords() invalid hit access at index " + std::to_string(ilayer));
48 const auto& hit = *m_hit_ptrs[ilayer];
49 if (hit.getHitType() == HitType::spacepoint) {
50 unsigned other_layer = (hit.getSide() == 0) ? ilayer + 1 : ilayer - 1;
51 target_r = (target_r + m_idealRadii[other_layer]) / 2.;
52 }
53
54 double hough_x = getHoughX();
55 double hough_y = getHoughY();
56
57 // Use the centralized computeIdealCoords function from FPGATrackSimFunctions
58 std::vector<float> coords = ::computeIdealCoords(hit, hough_x, hough_y, target_r, m_doDeltaGPhis, m_trackCorrType);
59
60 return coords;
61}
62
63float FPGATrackSimTrack::getEtaCoord(int ilayer) const {
64 auto coords = getCoords(ilayer);
65 if (coords.size() > 0) {
66 return coords.at(0);
67 }
68 else {
69 throw std::range_error("FPGATrackSimTrack::getCoord(layer,coord) out of bounds");
70 }
71}
72
73float FPGATrackSimTrack::getPhiCoord(int ilayer) const {
74 auto coords = getCoords(ilayer);
75 // If this is a spacepoint, and if this is the "outer" hit on a strip module
76 // (side = 1) then we actually return the z/eta coord.
77 // Since spacepoints are duplicated, this avoids using the same phi coord
78 // twice and alsp avoids having to teach the code that strip spacepoints are
79 // "2D" hits despite being in the strips, which everything assumes is 1D.
80 // This makes it easy to mix and match spacepoints with strip hits that aren't
81 // spacepoints (since the number of strip layers is held fixed).
82 unsigned target_coord = 1;
83 if (!m_hit_ptrs.empty()) {
84 const auto& hit_ptr = m_hit_ptrs.at(ilayer);
85 if (hit_ptr && hit_ptr->getHitType() == HitType::spacepoint && (hit_ptr->getPhysLayer() % 2) == 1) {
86 target_coord = 0;
87 }
88 } else if (!m_hits.empty()) {
89 if (m_hits.at(ilayer).getHitType() == HitType::spacepoint && (m_hits.at(ilayer).getPhysLayer() % 2) == 1) {
90 target_coord = 0;
91 }
92 }
93
94 if (coords.size() > target_coord) {
95 return coords.at(target_coord);
96 }
97 else {
98 throw std::range_error("FPGATrackSimTrack::getCoord(layer,coord) out of bounds");
99 }
100}
101
103 int nCoords = 0;
104 if (!m_hit_ptrs.empty()) {
105 for (const auto& hit : m_hit_ptrs) {
106 if (hit) nCoords += hit->getDim();
107 }
108 }
109 else {
110 for (const auto& hit : m_hits) {
111 nCoords += hit.getDim();
112 }
113 }
114 return nCoords;
115}
116
117// Set a specific transient hit (shared_ptr only).
118// Caller is responsible for creating the shared_ptr:
119// - For owned/synthetic hits: pass std::make_shared<FPGATrackSimHit>(...)
120// - For SG hits: pass std::shared_ptr<const FPGATrackSimHit>(ptr, [](auto*){})
121// This only modifies m_hit_ptrs; use persistifyHits() to copy to m_hits.
122void FPGATrackSimTrack::setFPGATrackSimHit(unsigned i, std::shared_ptr<const FPGATrackSimHit> hit)
123{
124 if (m_hit_ptrs.size() <= i) m_hit_ptrs.resize(i+1);
125 m_hit_ptrs[i] = std::move(hit);
126}
127
130{
131 // Pre-fill with dummy hits to ensure dense vector model.
132 // This guarantees that all layers 0 to dim-1 have entries (no sparse nulls).
133 // setFPGATrackSimHit() will replace these dummies with real hits as needed.
134 m_hit_ptrs.clear();
135 m_hit_ptrs.reserve(dim);
136 for (int i = 0; i < dim; i++) {
137 FPGATrackSimHit dummy;
138 dummy.setLayer(i);
139 dummy.setSection(0);
140 m_hit_ptrs.push_back(std::make_shared<FPGATrackSimHit>(dummy));
141 }
142}
143
144
145// if ForceRange==true, then phi = [-pi..pi)
146void FPGATrackSimTrack::setPhi(float phi, bool ForceRange) {
147 if (ForceRange) {
148 // when phi is ridiculously large, there is no point in adjusting it
149 if (std::abs(phi) > 100) {
150 if (m_chi2 < 100) { // this is a BAD track, so fail it if chi2 hasn't done so already
151 m_chi2 += 100; // we want to fail this event anyway
152 }
153 }
154 else {
155 while (phi >= M_PI) phi -= (2. * M_PI);
156 while (phi < -M_PI) phi += (2. * M_PI);
157 }
158 }
159 m_phi = phi;
160}
161
163{
164 switch (ipar) {
165 case 0:
166 return m_qoverpt;
167 break;
168 case 1:
169 return m_d0;
170 break;
171 case 2:
172 return m_phi;
173 break;
174 case 3:
175 return m_z0;
176 break;
177 case 4:
178 return m_eta;
179 break;
180 }
181
182 return 0.;
183}
184
185
186void FPGATrackSimTrack::setParameter(int ipar, float val)
187{
188 switch (ipar) {
189 case 0:
190 m_qoverpt = val;
191 break;
192 case 1:
193 m_d0 = val;
194 break;
195 case 2:
196 m_phi = val;
197 break;
198 case 3:
199 m_z0 = val;
200 break;
201 case 4:
202 m_eta = val;
203 break;
204 }
205}
206
207
208ostream& operator<<(ostream& out, const FPGATrackSimTrack& track)
209{
210
211 out << "TRACK: ID=" << std::left << setw(8) << track.m_trackID;
212 out << " SECTOR1=" << std::left << setw(8) << track.m_firstSectorID;
213 out << " BANK=" << std::left << setw(8) << track.m_bankID;
214 out << " BARCODE=" << std::left << setw(6) << track.m_barcode;
215 out << " BARCODE_F=" << std::left << setw(9) << track.m_barcode_frac;
216 out << " EVENT=" << std::left << setw(6) << track.m_eventindex;
217 out << " HITMAP=" << std::left << setw(8) << track.getHitMap();
218 out << " TYPE=" << std::left << setw(3) << track.m_typemask;
219 out << " NMISS=" << std::left << setw(3) << track.getNMissing();
220 out << "\n";
221 streamsize oldprec = out.precision();
222 out.precision(4);
223 out << " PHI=" << std::left << setw(10) << track.m_phi;
224 out.setf(ios_base::scientific);
225 out.precision(2);
226 out << " Q/PT=" << std::left << setw(10) << track.m_qoverpt;
227 out.unsetf(ios_base::scientific);
228 out.precision(4);
229 out << " d0=" << std::left << setw(10) << track.m_d0;
230 out << " ETA=" << std::left << setw(10) << track.m_eta;
231 out << " z0=" << std::left << setw(10) << track.m_z0;
232 out << " Chi2=" << std::left << setw(12) << track.m_chi2;
233 out << " OChi2=" << std::left << setw(12) << track.m_origchi2;
234
235 out << endl;
236 out.precision(oldprec);
237
238 out << endl;
239
240 // print the hits
241 int iter = 0;
242 for (const auto& hit : track.m_hits) {
243 out << "Hit " << iter << ": " << hit << "\n";
244 iter++;
245 }
246
247 return out;
248}
249
250
252{
253 vector<FPGATrackSimMultiTruth> mtv;
254 mtv.reserve(m_hit_ptrs.size());
255
256 // don't loop over coordinates, since we only calculate truth *per hit* and not per coordinate, though hitmap is saved for coordinates, so be careful
257 if (!m_hit_ptrs.empty()) {
258 for (const auto& thishit : m_hit_ptrs)
259 {
260 if (!thishit) throw std::runtime_error("Null hit pointer in FPGATrackSimTrack::calculateTruth()");
261 if (thishit->isReal())
262 {
263 FPGATrackSimMultiTruth this_mt(thishit->getTruth());
265 if (thishit->isPixel())
266 for ( auto& x : this_mt)
267 x.second *= 2;
268 mtv.push_back(this_mt);
269 }
270 }
271 }
272 else {
273 for (const auto& thishit : m_hits)
274 {
275 if (thishit.isReal())
276 {
277 FPGATrackSimMultiTruth this_mt(thishit.getTruth());
279 if (thishit.isPixel())
280 for ( auto& x : this_mt)
281 x.second *= 2;
282 mtv.push_back(this_mt);
283 }
284 }
285 }
286
287 // compute the best geant match, the barcode with the largest number of hits contributing to the track.
288 // frac is then the fraction of the total number of hits on the track attributed to the barcode.
289 FPGATrackSimMultiTruth mt(std::accumulate(mtv.begin(), mtv.end(), FPGATrackSimMultiTruth(), FPGATrackSimMultiTruth::AddAccumulator()));
292 const bool ok = mt.best(tbarcode, tfrac);
293 if (ok)
294 {
295 setEventIndex(tbarcode.first);
296 setBarcode(tbarcode.second);
297 setBarcodeFrac(tfrac);
298 }
299 else
300 {
301 setEventIndex(-1);
302 setBarcode(-1);
304 }
305}
306
307void FPGATrackSimTrack::setPassedOR(unsigned int code)
308{
309 m_ORcode = code;
310}
311
312
314 unsigned retv =0;
315 for (unsigned lyr = 0; lyr < m_hit_ptrs.size(); lyr++)
316 {
317 if (m_hit_ptrs[lyr] && m_hit_ptrs[lyr]->isReal()) retv|=(1<< lyr);
318 }
319 return retv;
320}
#define M_PI
Scalar phi() const
phi method
uint32_t layer_bitmask_t
#define x
bool best(FPGATrackSimMultiTruth::Barcode &code, FPGATrackSimMultiTruth::Weight &weight) const
std::pair< unsigned long, unsigned long > Barcode
void setParameter(int, float)
TrackCorrType m_trackCorrType
void setPassedOR(unsigned int)
void setEventIndex(const signed long &v)
float getHoughX() const
layer_bitmask_t getHitMask() const
float getEtaCoord(int ilayer) const
void setPhi(float v, bool ForceRange=true)
std::vector< float > getCoords(unsigned ilayer) const
void setBarcode(const HepMcParticleLink::barcode_type &v)
void setFPGATrackSimHit(unsigned i, std::shared_ptr< const FPGATrackSimHit > hit)
float getHoughY() const
std::vector< std::shared_ptr< const FPGATrackSimHit > > m_hit_ptrs
std::vector< double > m_idealRadii
void setBarcodeFrac(const float &v)
std::vector< float > computeIdealCoords(unsigned ilayer) const
void setNLayers(int)
set the number of layers in the track.
std::vector< FPGATrackSimHit > m_hits
float getPhiCoord(int ilayer) const
FPGATrackSimTrack()=default
float getParameter(int) const
STL namespace.
ostream & operator<<(ostream &s, const SG::VarHandleKey &m)