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