ATLAS Offline Software
Loading...
Searching...
No Matches
FPGAActsTrkConverter.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
5#include "Acts/Surfaces/PerigeeSurface.hpp"
8
9#include <format>
10#include <sstream>
11//Heavily inspired by https://gitlab.cern.ch/atlas/athena/-/blob/main/Tracking/Acts/ActsTrackReconstruction/src/RandomProtoTrackCreator.cxx
12
14 const std::string& name,
15 const IInterface* parent): base_class(type,name,parent) { }
16
17
19
20 ATH_MSG_DEBUG("Initializing FPGAActsTrkConverter...");
21
22 // Get SCT & pixel Identifier helpers
23 ATH_CHECK(detStore()->retrieve(m_pixelId, "PixelID"));
24 ATH_CHECK(detStore()->retrieve(m_SCTId, "SCT_ID"));
25
26 return StatusCode::SUCCESS;
27
28}
29
30StatusCode FPGAActsTrkConverter::findProtoTracks(const EventContext& ctx,
31 const xAOD::PixelClusterContainer & pixelContainer,
32 const xAOD::StripClusterContainer & stripContainer,
33 std::vector<ActsTrk::ProtoTrack> & foundProtoTracks,
34 const std::vector<FPGATrackSimRoad>& roads) const {
35
36 ATH_MSG_INFO("Creating Acts proto-tracks from FPGA roads...");
37
38 if (roads.size() > 0) {
39 std::unordered_map<xAOD::DetectorIdentType, const xAOD::PixelCluster*> pixelClusterMap;
40 for (const xAOD::PixelCluster* cluster : pixelContainer) {
41 pixelClusterMap.emplace(cluster->identifier(), cluster);
42 }
43
44 std::unordered_map<xAOD::DetectorIdentType, const xAOD::StripCluster*> stripClusterMap;
45 for (const xAOD::StripCluster* cluster : stripContainer) {
46 stripClusterMap.emplace(cluster->identifier(), cluster);
47
48 }
49 for (const FPGATrackSimRoad& road : roads) {
50 std::vector<ActsTrk::ATLASUncalibSourceLink> points;
51
52 // Process measurements directly from road's shared_ptr hits
53 for (size_t l = 0; l < road.getNLayers(); ++l) {
54 for (const auto& layerH : road.getHitPtrs(l)) {
55 if (!layerH || !layerH->isReal()) continue;
56
57 if (layerH->isPixel()) {
58 ATH_MSG_DEBUG("Looking for Pixel cluster to match");
59 auto it = pixelClusterMap.find(layerH->getRdoIdentifier());
60 if (it != pixelClusterMap.end()) {
61 ATH_CHECK(matchTrackMeasurements<xAOD::PixelCluster>(ctx, *(it->second), *layerH, points, pixelContainer));
62 }
63 }
64 else if (layerH->isStrip()) {
65 ATH_MSG_DEBUG("Looking for Strip cluster to match");
66 auto it = stripClusterMap.find(layerH->getRdoIdentifier());
67 if (it != stripClusterMap.end()) {
68 ATH_CHECK(matchTrackMeasurements<xAOD::StripCluster>(ctx, *(it->second), *layerH, points, stripContainer));
69 }
70 }
71 else {
72 ATH_MSG_ERROR("FPGA hit not classified as pixel or strip");
73 return StatusCode::FAILURE;
74 }
75 }
76 }
77
78 if (points.size()) {
79 std::unique_ptr<Acts::BoundTrackParameters> inputPerigee = makeParams(road);
80 foundProtoTracks.emplace_back(points, std::move(inputPerigee));
81 ATH_MSG_INFO("Made a prototrack with " << points.size() << " measurements");
82 }
83 }
84 }
85
86 return StatusCode::SUCCESS;
87}
88
89StatusCode FPGAActsTrkConverter::findProtoTracks(const EventContext& ctx,
90 const xAOD::PixelClusterContainer& pixelContainer,
91 const xAOD::StripClusterContainer& stripContainer,
92 std::vector<ActsTrk::ProtoTrack>& foundProtoTracks,
93 const std::vector<FPGATrackSimTrack>& tracks) const {
94
95 ATH_MSG_INFO("Creating Acts proto-tracks from FPGA tracks...");
96 // Initialize unordered maps for pixel and strip clusters
97 std::unordered_map<xAOD::DetectorIdentType, const xAOD::PixelCluster*> pixelClusterMap;
98 for (const xAOD::PixelCluster* cluster : pixelContainer) {
99 pixelClusterMap.emplace(cluster->identifier(), cluster);
100 }
101
102 std::unordered_map<xAOD::DetectorIdentType, const xAOD::StripCluster*> stripClusterMap;
103 for (const xAOD::StripCluster* cluster : stripContainer) {
104 stripClusterMap.emplace(cluster->identifier(), cluster);
105 }
106 for (const FPGATrackSimTrack& track : tracks) {
107 if (not track.passedOR()) continue;
108 std::vector<ActsTrk::ATLASUncalibSourceLink> points;
109 const auto& hits = track.getFPGATrackSimHitPtrs();
110 for (const auto& hit : hits) {
111 if (!hit->isReal()) continue;
112
113 if (hit->isPixel()) {
114 ATH_MSG_DEBUG("Looking for Pixel cluster to match");
115 auto it = pixelClusterMap.find(hit->getRdoIdentifier());
116 if (it != pixelClusterMap.end()) {
117 ATH_CHECK(matchTrackMeasurements<xAOD::PixelCluster>(ctx, *(it->second), *hit, points, pixelContainer));
118 }
119 }
120 else if (hit->isStrip()) {
121 ATH_MSG_DEBUG("Looking for Strip cluster to match");
122 auto it = stripClusterMap.find(hit->getRdoIdentifier());
123 if (it != stripClusterMap.end()) {
124 ATH_CHECK(matchTrackMeasurements<xAOD::StripCluster>(ctx, *(it->second), *hit, points, stripContainer));
125 }
126 }
127 else {
128 ATH_MSG_ERROR("FPGA hit not classified as pixel or strip");
129 return StatusCode::FAILURE;
130 }
131 }
132
133 if (points.size()) {
134 ATH_MSG_DEBUG("\tMaking a proto-track with " << points.size() << " clusters");
135 std::unique_ptr<Acts::BoundTrackParameters> inputPerigee = makeParams(track);
136 foundProtoTracks.emplace_back(points, std::move(inputPerigee));
137 }
138 }
139 return StatusCode::SUCCESS;
140}
141
142
143template <typename XAOD_CLUSTER>
144StatusCode FPGAActsTrkConverter::matchTrackMeasurements(const EventContext& ctx,
145 const XAOD_CLUSTER& cluster,
146 const FPGATrackSimHit & trackHit,
147 std::vector<ActsTrk::ATLASUncalibSourceLink>& measurements,
148 const DataVector<XAOD_CLUSTER>& clusterContainer) const
149{
150 const Identifier::value_type trackId = (trackHit.getHitType() == HitType::spacepoint)
151 ? trackHit.getOriginalHit().getRdoIdentifier()
152 : trackHit.getRdoIdentifier();
153
154 if(cluster.identifier() == trackId) {
155 measurements.emplace_back(ActsTrk::makeATLASUncalibSourceLink(&clusterContainer, cluster.index(), ctx));
156 ATH_MSG_DEBUG("Matched FPGATrackSimHit to xAOD cluster");
157 }
158
159 return StatusCode::SUCCESS;
160}
161
162std::unique_ptr<Acts::BoundTrackParameters> FPGAActsTrkConverter::makeParams (const FPGATrackSimRoad &road) const{
163 using namespace Acts::UnitLiterals;
164
165 std::shared_ptr<const Acts::Surface> actsSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(0., 0., 0.));
166 Acts::BoundVector params;
167
168 constexpr double GeVToMeV = 1000;
169 double d0=0.; //?
170 double z0=0.; //?
171 double phi=road.getX();
172 double eta=0.2;
173 double theta=2*std::atan(std::exp(-eta));
174 double qop = (std::abs(road.getY()) > 1E-9) ? road.getY()/GeVToMeV : 1E-12;
175 double t=0.; //?
176 ATH_MSG_DEBUG("\tphi=" <<phi << " eta=" << eta << " qop=" << qop);
177
178 params << d0, z0, phi, theta, qop, t;
179
180 // Covariance - TODO
181 Acts::BoundMatrix cov = Acts::BoundMatrix::Identity();
182 cov *= (GeVToMeV*GeVToMeV);
183
184 // some ACTS paperwork
186 float mass = Trk::ParticleMasses::mass[hypothesis] * Acts::UnitConstants::MeV;
187 Acts::PdgParticle absPdg = Acts::makeAbsolutePdgParticle(Acts::ePionPlus);
188 Acts::ParticleHypothesis actsHypothesis{
189 absPdg, mass, Acts::AnyCharge{1.0f}};
190
191 return std::make_unique<Acts::BoundTrackParameters>(actsSurface, params,
192 cov, actsHypothesis);
193
194}
195
196
197std::unique_ptr<Acts::BoundTrackParameters> FPGAActsTrkConverter::makeParams (const FPGATrackSimTrack &track) const{
198
199 using namespace Acts::UnitLiterals;
200 std::shared_ptr<const Acts::Surface> actsSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(0., 0., 0.));
201 Acts::BoundVector params;
202
203 constexpr double GeVToMeV = 1000.;
204 double d0=track.getD0();
205 double z0=track.getZ0();
206 double phi=track.getPhi();
207 double eta=track.getEta();
208 double theta=track.getTheta();
209 double qopt=track.getQOverPt()*GeVToMeV;
210 double pt=track.getPt()/GeVToMeV;
211 double px=pt*std::cos(phi);
212 double py=pt*std::sin(phi);
213 double pz=pt*std::sinh(eta);
214 double p=std::sqrt(px*px+py*py+pz*pz);
215 double qop=((p > 1e-10) ? (1/p) : 1e10);
216 if (qopt < 0) qop *= -1;
217 double t=0.;
218
219 params << d0, z0, phi, theta, qop, t;
220 ATH_MSG_DEBUG("\td0= " << d0 << " z0=" <<z0 << " phi=" <<phi << " theta=" << theta<< " qoverp=" << qop);
221
222 // Covariance - let's be honest and say we have no clue ;-)
223 Acts::BoundMatrix cov = Acts::BoundMatrix::Identity();
224
225 (cov)(0,0) *= 0.16; // d0: 0.4 **2 (conservative)
226 (cov)(1,1) *= 25; // z0: 5**2 = 25 (conservative)
227 (cov)(2,2) *= 0.0008; // phi: 0.02**2 = 0.0004, increase a bit = double
228 (cov)(3,3) *= 0.0008; // width in eta is nearly 0.2, but width in theta = 2*atan(e^-eta) will vary. Take biggest one, which is at eta of 0 when width is 0.02, so get 0.02**2 = 0.0004, increase a bit = double
229 (cov)(4,4) *= 0.36; // qop also varies with eta. Error on q/pt conservatively = 0.0003 in mev ^-1, or 0.3 in gev ^-1, double to start giving us 0.6. then square that to get 0.36
230
231
232
233 // some ACTS paperwork
235 float mass = Trk::ParticleMasses::mass[hypothesis] * Acts::UnitConstants::MeV;
236 Acts::PdgParticle absPdg = Acts::makeAbsolutePdgParticle(Acts::ePionPlus);
237 Acts::ParticleHypothesis actsHypothesis{
238 absPdg, mass, Acts::AnyCharge{1.0f}};
239
240 return std::make_unique<Acts::BoundTrackParameters>(actsSurface, params,
241 cov, actsHypothesis);
242
243}
244
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
Derived DataVector<T>.
Definition DataVector.h:795
FPGAActsTrkConverter(const std::string &type, const std::string &name, const IInterface *parent)
std::unique_ptr< Acts::BoundTrackParameters > makeParams(const FPGATrackSimRoad &road) const
virtual StatusCode initialize() override final
StatusCode matchTrackMeasurements(const EventContext &ctx, const XAOD_CLUSTER &cluster, const FPGATrackSimHit &trackHit, std::vector< ActsTrk::ATLASUncalibSourceLink > &measurements, const DataVector< XAOD_CLUSTER > &clusterContainer) const
virtual StatusCode findProtoTracks(const EventContext &ctx, const xAOD::PixelClusterContainer &pixelContainer, const xAOD::StripClusterContainer &stripContainer, std::vector< ActsTrk::ProtoTrack > &foundProtoTracks, const std::vector< FPGATrackSimRoad > &roads) const override final
Identifier::value_type getRdoIdentifier() const
const FPGATrackSimHit getOriginalHit() const
HitType getHitType() const
float getY() const
float getX() const
ATLASUncalibSourceLink makeATLASUncalibSourceLink(const xAOD::UncalibratedMeasurementContainer *container, std::size_t index, const EventContext &ctx)
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
PixelClusterContainer_v1 PixelClusterContainer
Define the version of the pixel cluster container.
StripCluster_v1 StripCluster
Define the version of the strip cluster class.
StripClusterContainer_v1 StripClusterContainer
Define the version of the strip cluster container.
PixelCluster_v1 PixelCluster
Define the version of the pixel cluster class.