ATLAS Offline Software
Loading...
Searching...
No Matches
SpacepointFeatureTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include <cmath>
7
12
15
17 const std::string& name,
18 const IInterface* parent)
19 : base_class(type, name, parent), m_SCT_ID(nullptr) {
20 declareInterface<ISpacepointFeatureTool>(this);
21}
22
24 // Grab PixelID helper
25 ATH_CHECK (detStore()->retrieve(m_pixelID, "PixelID") );
26
27 // Grab SCT_ID helper
28 ATH_CHECK (detStore()->retrieve(m_SCT_ID,"SCT_ID") );
29
30 return StatusCode::SUCCESS;
31}
32
33std::map<std::string, float> InDet::SpacepointFeatureTool::getFeatures(
34 const Trk::SpacePoint* sp) const {
35 // see the naming conventions in ACORN
36 // https://gitlab.cern.ch/gnn4itkteam/acorn/-/blob/dev/acorn/stages/data_reading/models/athena_root_utils.py?ref_type=heads#L19
37 std::map<std::string, float> features;
38 features["x"] = sp->globalPosition().x();
39 features["y"] = sp->globalPosition().y();
40 features["z"] = sp->globalPosition().z();
41 features["r"] = sp->r();
42 features["phi"] = sp->phi();
43 features["eta"] = sp->eta();
44
45 const InDet::SiCluster *cluster_1 = static_cast<const InDet::SiCluster *>(sp->clusterList().first);
46 // get the cluster position
47 features["cluster_x_1"] = cluster_1->globalPosition().x();
48 features["cluster_y_1"] = cluster_1->globalPosition().y();
49 features["cluster_z_1"] = cluster_1->globalPosition().z();
50 features["cluster_r_1"] = std::sqrt(cluster_1->globalPosition().x() * cluster_1->globalPosition().x() + cluster_1->globalPosition().y() * cluster_1->globalPosition().y());
51 features["cluster_phi_1"] = std::atan2(cluster_1->globalPosition().y(), cluster_1->globalPosition().x());
52 features["cluster_eta_1"] = -1 * std::log(std::tan(0.5 * std::atan2(features["cluster_r_1"], features["cluster_z_1"])));
53
54 const InDet::SiCluster *cluster_2 = static_cast<const InDet::SiCluster *>(sp->clusterList().second);
55 bool isStrip = (cluster_2 != nullptr);
56
57 // get the cluster shape
58 float charge_count_1 = 0;
59 int pixel_count_1 = 0;
60 float loc_eta_1 = 0, loc_phi_1 = 0; // clusterShape: [leta, lphi]
61 float glob_eta_1 = 0, glob_phi_1 = 0; // clusterShape: [geta, gphi]
62 float localDir0_1 = 0, localDir1_1 = 0, localDir2_1 = 0; // clusterShape: [lengthDir0, lengthDir1, lengthDir2]
63 float lengthDir0_1 = 0, lengthDir1_1 = 0, lengthDir2_1 = 0; // clusterShape: [lengthDir0, lengthDir1, lengthDir2]
64 float eta_angle_1 = 0, phi_angle_1 = 0;
65 // module ID
66 uint64_t module_id = cluster_1->detectorElement()->identify().get_compact();
67 features["module_id"] = static_cast<float>(module_id);
68
69 // 1: {hardware: PIXEL, barrel_endcap: -2}
70 // 2: {hardware: STRIP, barrel_endcap: -2}
71 // 3: {hardware: PIXEL, barrel_endcap: 0}
72 // 4: {hardware: STRIP, barrel_endcap: 0}
73 // 5: {hardware: PIXEL, barrel_endcap: 2}
74 // 6: {hardware: STRIP, barrel_endcap: 2}
75 int region = 0;
76
77 if (!isStrip) {
78 const InDet::PixelCluster* cluster = dynamic_cast<const InDet::PixelCluster*>(cluster_1);
79 const InDetDD::SiDetectorElement *element = cluster->detectorElement();
80 int barrel_endcap = m_pixelID->barrel_ec(cluster->identify());
81 switch (barrel_endcap) {
82 case -2:
83 region = 1;
84 break;
85 case 0:
86 region = 3;
87 break;
88 case 2:
89 region = 5;
90 break;
91 default:
92 ATH_MSG_ERROR("Unknown barrel_endcap: " << barrel_endcap);
93 break;
94 }
95
96
97 // boundary of the cluster in the local module.
98 int min_eta = 999;
99 int min_phi = 999;
100 int max_eta = -999;
101 int max_phi = -999;
102 for (unsigned int rdo = 0; rdo < cluster->rdoList().size(); rdo++) {
103 charge_count_1 += cluster->totList().at(rdo);
104 ++ pixel_count_1;
105
106 const auto &rdoID = cluster->rdoList().at(rdo);
107 InDetDD::SiCellId cellID = element->cellIdFromIdentifier(rdoID);
108 int phi = cellID.phiIndex();
109 int eta = cellID.etaIndex();
110 if (min_eta > eta)
111 min_eta = eta;
112 if (min_phi > phi)
113 min_phi = phi;
114 if (max_eta < eta)
115 max_eta = eta;
116 if (max_phi < phi)
117 max_phi = phi;
118 }
119
120
121 const InDetDD::PixelModuleDesign *design = dynamic_cast<const InDetDD::PixelModuleDesign *>(&element->design());
122
123 InDetDD::SiLocalPosition localPos_entry = design->localPositionOfCell(InDetDD::SiCellId(min_phi, min_eta));
124 InDetDD::SiLocalPosition localPos_exit = design->localPositionOfCell(InDetDD::SiCellId(max_phi, max_eta));
125
126 Amg::Vector3D localStartPosition(localPos_entry.xEta() - 0.5 * element->etaPitch(),
127 localPos_entry.xPhi() - 0.5 * element->phiPitch(),
128 -0.5 * element->thickness());
129 Amg::Vector3D localEndPosition(localPos_exit.xEta() + 0.5 * element->etaPitch(),
130 localPos_exit.xPhi() + 0.5 * element->phiPitch(), 0.5 * element->thickness());
131
132 // local direction in local coordinates
133 Amg::Vector3D localDirection = localEndPosition - localStartPosition;
134 cartesion_to_spherical(localDirection, loc_eta_1, loc_phi_1);
135
136 localDir0_1 = localDirection[0];
137 localDir1_1 = localDirection[1];
138 localDir2_1 = localDirection[2];
139
140 Amg::Vector3D globalStartPosition = element->globalPosition(localStartPosition);
141 Amg::Vector3D globalEndPosition = element->globalPosition(localEndPosition);
142
143 Amg::Vector3D direction = globalEndPosition - globalStartPosition;
144 cartesion_to_spherical(direction, glob_eta_1, glob_phi_1);
145
146 Amg::Vector3D my_phiax = element->phiAxis();
147 Amg::Vector3D my_etaax = element->etaAxis();
148 Amg::Vector3D my_normal = element->normal();
149
150 float trkphicomp = direction.dot(my_phiax);
151 float trketacomp = direction.dot(my_etaax);
152 float trknormcomp = direction.dot(my_normal);
153 eta_angle_1 = atan2(trknormcomp, trketacomp);
154 phi_angle_1 = atan2(trknormcomp, trkphicomp);
155 } else {
156 // first cluster of the strip detector.
157 auto status = getSCTClusterShapeInfo_fn(cluster_1, charge_count_1, pixel_count_1, loc_eta_1, loc_phi_1,
158 glob_eta_1, glob_phi_1,
159 localDir0_1, localDir1_1, localDir2_1,
160 lengthDir0_1, lengthDir1_1, lengthDir2_1,
161 eta_angle_1, phi_angle_1
162 );
163 if (status.isFailure()) {
164 ATH_MSG_ERROR("Failed at " << __LINE__ << " of getting SCT cluster shape info.");
165 }
166 auto cluster = dynamic_cast<const InDet::SCT_Cluster*>(cluster_1);
167 int barrel_endcap = m_SCT_ID->barrel_ec(cluster->identify());
168 switch (barrel_endcap) {
169 case -2:
170 region = 2;
171 break;
172 case 0:
173 region = 4;
174 break;
175 case 2:
176 region = 6;
177 break;
178 default:
179 ATH_MSG_ERROR("Unknown barrel_endcap: " << barrel_endcap);
180 break;
181 }
182 }
183 features["charge_count_1"] = charge_count_1;
184 features["count_1"] = pixel_count_1;
185 features["loc_eta_1"] = loc_eta_1;
186 features["loc_phi_1"] = loc_phi_1;
187 features["glob_eta_1"] = glob_eta_1;
188 features["glob_phi_1"] = glob_phi_1;
189 features["localDir0_1"] = localDir0_1;
190 features["localDir1_1"] = localDir1_1;
191 features["localDir2_1"] = localDir2_1;
192 features["lengthDir0_1"] = lengthDir0_1;
193 features["lengthDir1_1"] = lengthDir1_1;
194 features["lengthDir2_1"] = lengthDir2_1;
195 features["eta_angle_1"] = eta_angle_1;
196 features["phi_angle_1"] = phi_angle_1;
197 features["region"] = region;
198
199 if (isStrip) {
200 features["cluster_x_2"] = cluster_2->globalPosition().x();
201 features["cluster_y_2"] = cluster_2->globalPosition().y();
202 features["cluster_z_2"] = cluster_2->globalPosition().z();
203 features["cluster_r_2"] = std::sqrt(cluster_2->globalPosition().x() * cluster_2->globalPosition().x() + cluster_2->globalPosition().y() * cluster_2->globalPosition().y());
204 features["cluster_phi_2"] = std::atan2(cluster_2->globalPosition().y(), cluster_2->globalPosition().x());
205 features["cluster_eta_2"] = -1 * std::log(std::tan(0.5 * std::atan2(features["cluster_r_2"], features["cluster_z_2"])));
206 // the second cluster of the strip detector.
207 float charge_count_2 = 0;
208 int pixel_count_2 = 0;
209 float loc_eta_2 = 0, loc_phi_2 = 0; // clusterShape: [leta, lphi]
210 float glob_eta_2 = 0, glob_phi_2 = 0; // clusterShape: [geta, gphi]
211 float localDir0_2 = 0, localDir1_2 = 0, localDir2_2 = 0; // clusterShape: [lengthDir0, lengthDir1, lengthDir2]
212 float lengthDir0_2 = 0, lengthDir1_2 = 0, lengthDir2_2 = 0; // clusterShape: [lengthDir0, lengthDir1, lengthDir2]
213 float eta_angle_2 = 0, phi_angle_2 = 0;
214 auto status = getSCTClusterShapeInfo_fn(cluster_2, charge_count_2, pixel_count_2, loc_eta_2, loc_phi_2,
215 glob_eta_2, glob_phi_2,
216 localDir0_2, localDir1_2, localDir2_2,
217 lengthDir0_2, lengthDir1_2, lengthDir2_2,
218 eta_angle_2, phi_angle_2
219 );
220 if (status.isFailure()) {
221 ATH_MSG_ERROR("Failed at " << __LINE__ << " of getting SCT cluster shape info.");
222 }
223
224 features["charge_count_2"] = charge_count_2;
225 features["count_2"] = pixel_count_2;
226 features["loc_eta_2"] = loc_eta_2;
227 features["loc_phi_2"] = loc_phi_2;
228 features["glob_eta_2"] = glob_eta_2;
229 features["glob_phi_2"] = glob_phi_2;
230 features["localDir0_2"] = localDir0_2;
231 features["localDir1_2"] = localDir1_2;
232 features["localDir2_2"] = localDir2_2;
233 features["lengthDir0_2"] = lengthDir0_2;
234 features["lengthDir1_2"] = lengthDir1_2;
235 features["lengthDir2_2"] = lengthDir2_2;
236 features["eta_angle_2"] = eta_angle_2;
237 features["phi_angle_2"] = phi_angle_2;
238 } else {
239 // copy the cluster 1 to cluster 2.
240 features["cluster_x_2"] = features["cluster_x_1"];
241 features["cluster_y_2"] = features["cluster_y_1"];
242 features["cluster_z_2"] = features["cluster_z_1"];
243 features["cluster_r_2"] = features["cluster_r_1"];
244 features["cluster_phi_2"] = features["cluster_phi_1"];
245 features["cluster_eta_2"] = features["cluster_eta_1"];
246 features["charge_count_2"] = features["charge_count_1"];
247 features["count_2"] = features["count_1"];
248 features["loc_eta_2"] = features["loc_eta_1"];
249 features["loc_phi_2"] = features["loc_phi_1"];
250 features["glob_eta_2"] = features["glob_eta_1"];
251 features["glob_phi_2"] = features["glob_phi_1"];
252 features["localDir0_2"] = features["localDir0_1"];
253 features["localDir1_2"] = features["localDir1_1"];
254 features["localDir2_2"] = features["localDir2_1"];
255 features["lengthDir0_2"] = features["lengthDir0_1"];
256 features["lengthDir1_2"] = features["lengthDir1_1"];
257 features["lengthDir2_2"] = features["lengthDir2_1"];
258 features["eta_angle_2"] = features["eta_angle_1"];
259 features["phi_angle_2"] = features["phi_angle_1"];
260 }
261 return features;
262}
263
264
265void InDet::SpacepointFeatureTool::cartesion_to_spherical(const Amg::Vector3D &xyzVec, float &eta_, float &phi_) const {
266 float r3 = 0;
267 for (int idx = 0; idx < 3; ++idx) {
268 r3 += xyzVec[idx] * xyzVec[idx];
269 }
270 r3 = std::sqrt(r3);
271 phi_ = std::atan2(xyzVec[1], xyzVec[0]);
272 float theta_ = std::acos(xyzVec[2] / r3);
273 eta_ = std::log(std::tan(0.5 * theta_)); // a bug here, but keep it so it is consistent with the DumpObject.
274}
275
277 float &charge_count, int &pixel_count, float &loc_eta, float &loc_phi,
278 float &glob_eta, float &glob_phi,
279 float &localDir0, float &localDir1, float &localDir2,
280 float &lengthDir0, float &lengthDir1, float &lengthDir2,
281 float &eta_angle, float &phi_angle
282 ) const
283{
284 const InDet::SCT_Cluster* cluster = dynamic_cast<const InDet::SCT_Cluster*>(si_cluster);
285 const InDetDD::SiDetectorElement *element = cluster->detectorElement();
286 Amg::Vector2D locpos = cluster->localPosition();
287 std::pair<Amg::Vector3D, Amg::Vector3D> ends(
288 element->endsOfStrip(InDetDD::SiLocalPosition(locpos.y(), locpos.x(), 0)));
289 Amg::Vector3D JanDirection = ends.second - ends.first;
290 lengthDir0 = JanDirection[0];
291 lengthDir1 = JanDirection[1];
292 lengthDir2 = JanDirection[2];
293
294 // get local directions.
295 // retrieve cluster shape
296 const InDetDD::SCT_ModuleSideDesign *design(
297 dynamic_cast<const InDetDD::SCT_ModuleSideDesign *>(&element->design()));
298 if (not design) {
299 ATH_MSG_ERROR("Failed at " << __LINE__ << " of accessing SCT ModuleSide Design");
300 return StatusCode::FAILURE;
301 }
302
303 int min_strip = 999;
304 int max_strip = -999;
305
306 charge_count = 0;
307 pixel_count = 0;
308
309 for (unsigned int rdo = 0; rdo < cluster->rdoList().size(); rdo++) {
310 const auto &rdoID = cluster->rdoList().at(rdo);
311
312 int strip = m_SCT_ID->strip(rdoID);
313
314 if (min_strip > strip) min_strip = strip;
315 if (max_strip < strip) max_strip = strip;
316
317 ++pixel_count;
318 }
319
320 InDetDD::SiLocalPosition localPos_entry = design->localPositionOfCell(InDetDD::SiCellId(min_strip));
321 InDetDD::SiLocalPosition localPos_exit = design->localPositionOfCell(InDetDD::SiCellId(max_strip));
322
323 Amg::Vector3D localStartPosition(localPos_entry.xEta() - 0.5 * element->etaPitch(),
324 localPos_entry.xPhi() - 0.5 * element->phiPitch(),
325 -0.5 * element->thickness());
326 Amg::Vector3D localEndPosition(localPos_exit.xEta() + 0.5 * element->etaPitch(),
327 localPos_exit.xPhi() + 0.5 * element->phiPitch(), 0.5 * element->thickness());
328
329 Amg::Vector3D localDirection = localEndPosition - localStartPosition;
330 cartesion_to_spherical(localDirection, loc_eta, loc_phi);
331 localDir0 = localDirection[0];
332 localDir1 = localDirection[1];
333 localDir2 = localDirection[2];
334
335 Amg::Vector3D globalStartPosition = element->globalPosition(localStartPosition);
336 Amg::Vector3D globalEndPosition = element->globalPosition(localEndPosition);
337
338 Amg::Vector3D direction = globalEndPosition - globalStartPosition;
339 cartesion_to_spherical(direction, glob_eta, glob_phi);
340
341 Amg::Vector3D my_phiax = element->phiAxis();
342 Amg::Vector3D my_etaax = element->etaAxis();
343 Amg::Vector3D my_normal = element->normal();
344
345 float trkphicomp = direction.dot(my_phiax);
346 float trketacomp = direction.dot(my_etaax);
347 float trknormcomp = direction.dot(my_normal);
348 phi_angle = atan2(trknormcomp, trkphicomp);
349 eta_angle = atan2(trknormcomp, trketacomp);
350
351 return StatusCode::SUCCESS;
352}
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)
static Double_t sp
value_type get_compact() const
Get the compact id.
Class used to describe the design of a module (diode segmentation and readout scheme)
virtual SiLocalPosition localPositionOfCell(const SiCellId &cellId) const
readout or diode id -> position.
Base class for the SCT module side design, extended by the Forward and Barrel module design.
virtual SiLocalPosition localPositionOfCell(const SiCellId &cellId) const override=0
id -> position
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
int phiIndex() const
Get phi index. Equivalent to strip().
Definition SiCellId.h:122
int etaIndex() const
Get eta index.
Definition SiCellId.h:114
Class to hold geometrical description of a silicon detector element.
virtual SiCellId cellIdFromIdentifier(const Identifier &identifier) const override final
SiCellId from Identifier.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
double phiPitch() const
Pitch (inline methods)
std::pair< Amg::Vector3D, Amg::Vector3D > endsOfStrip(const Amg::Vector2D &position) const
Special method for SCT to retrieve the two ends of a "strip" Returned coordinates are in global frame...
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
double xPhi() const
position along phi direction:
double xEta() const
position along eta direction:
virtual const Amg::Vector3D & normal() const override final
Get reconstruction local normal axes in global frame.
HepGeom::Point3D< double > globalPosition(const HepGeom::Point3D< double > &localPos) const
transform a reconstruction local position into a global position (inline):
virtual Identifier identify() const override final
identifier of this detector element (inline)
double etaPitch() const
Pitch (inline methods)
const Amg::Vector3D & globalPosition() const
return global position reference
virtual const InDetDD::SiDetectorElement * detectorElement() const override final
return the detector element corresponding to this PRD The pointer will be zero if the det el is not d...
virtual std::map< std::string, float > getFeatures(const Trk::SpacePoint *) const override final
StatusCode initialize() override final
StatusCode getSCTClusterShapeInfo_fn(const InDet::SiCluster *si_cluster, float &charge_count, int &pixel_count, float &loc_eta, float &loc_phi, float &glob_eta, float &glob_phi, float &localDir0, float &localDir1, float &localDir2, float &lengthDir0, float &lengthDir1, float &lengthDir2, float &eta_angle, float &phi_angle) const
void cartesion_to_spherical(const Amg::Vector3D &xyzVec, float &eta_, float &phi_) const
const Amg::Vector2D & localPosition() const
return the local position reference
Identifier identify() const
return the identifier
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D