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
66 // 1: {hardware: PIXEL, barrel_endcap: -2}
67 // 2: {hardware: STRIP, barrel_endcap: -2}
68 // 3: {hardware: PIXEL, barrel_endcap: 0}
69 // 4: {hardware: STRIP, barrel_endcap: 0}
70 // 5: {hardware: PIXEL, barrel_endcap: 2}
71 // 6: {hardware: STRIP, barrel_endcap: 2}
72 int region = 0;
73
74 if (!isStrip) {
75 const InDet::PixelCluster* cluster = dynamic_cast<const InDet::PixelCluster*>(cluster_1);
76 const InDetDD::SiDetectorElement *element = cluster->detectorElement();
77 int barrel_endcap = m_pixelID->barrel_ec(cluster->identify());
78 switch (barrel_endcap) {
79 case -2:
80 region = 1;
81 break;
82 case 0:
83 region = 3;
84 break;
85 case 2:
86 region = 5;
87 break;
88 default:
89 ATH_MSG_ERROR("Unknown barrel_endcap: " << barrel_endcap);
90 break;
91 }
92
93
94 // boundary of the cluster in the local module.
95 int min_eta = 999;
96 int min_phi = 999;
97 int max_eta = -999;
98 int max_phi = -999;
99 for (unsigned int rdo = 0; rdo < cluster->rdoList().size(); rdo++) {
100 charge_count_1 += cluster->totList().at(rdo);
101 ++ pixel_count_1;
102
103 const auto &rdoID = cluster->rdoList().at(rdo);
104 InDetDD::SiCellId cellID = element->cellIdFromIdentifier(rdoID);
105 int phi = cellID.phiIndex();
106 int eta = cellID.etaIndex();
107 if (min_eta > eta)
108 min_eta = eta;
109 if (min_phi > phi)
110 min_phi = phi;
111 if (max_eta < eta)
112 max_eta = eta;
113 if (max_phi < phi)
114 max_phi = phi;
115 }
116
117
118 const InDetDD::PixelModuleDesign *design = dynamic_cast<const InDetDD::PixelModuleDesign *>(&element->design());
119
120 InDetDD::SiLocalPosition localPos_entry = design->localPositionOfCell(InDetDD::SiCellId(min_phi, min_eta));
121 InDetDD::SiLocalPosition localPos_exit = design->localPositionOfCell(InDetDD::SiCellId(max_phi, max_eta));
122
123 Amg::Vector3D localStartPosition(localPos_entry.xEta() - 0.5 * element->etaPitch(),
124 localPos_entry.xPhi() - 0.5 * element->phiPitch(),
125 -0.5 * element->thickness());
126 Amg::Vector3D localEndPosition(localPos_exit.xEta() + 0.5 * element->etaPitch(),
127 localPos_exit.xPhi() + 0.5 * element->phiPitch(), 0.5 * element->thickness());
128
129 // local direction in local coordinates
130 Amg::Vector3D localDirection = localEndPosition - localStartPosition;
131 cartesion_to_spherical(localDirection, loc_eta_1, loc_phi_1);
132
133 localDir0_1 = localDirection[0];
134 localDir1_1 = localDirection[1];
135 localDir2_1 = localDirection[2];
136
137 Amg::Vector3D globalStartPosition = element->globalPosition(localStartPosition);
138 Amg::Vector3D globalEndPosition = element->globalPosition(localEndPosition);
139
140 Amg::Vector3D direction = globalEndPosition - globalStartPosition;
141 cartesion_to_spherical(direction, glob_eta_1, glob_phi_1);
142
143 Amg::Vector3D my_phiax = element->phiAxis();
144 Amg::Vector3D my_etaax = element->etaAxis();
145 Amg::Vector3D my_normal = element->normal();
146
147 float trkphicomp = direction.dot(my_phiax);
148 float trketacomp = direction.dot(my_etaax);
149 float trknormcomp = direction.dot(my_normal);
150 eta_angle_1 = atan2(trknormcomp, trketacomp);
151 phi_angle_1 = atan2(trknormcomp, trkphicomp);
152 } else {
153 // first cluster of the strip detector.
154 auto status = getSCTClusterShapeInfo_fn(cluster_1, charge_count_1, pixel_count_1, loc_eta_1, loc_phi_1,
155 glob_eta_1, glob_phi_1,
156 localDir0_1, localDir1_1, localDir2_1,
157 lengthDir0_1, lengthDir1_1, lengthDir2_1,
158 eta_angle_1, phi_angle_1
159 );
160 if (status.isFailure()) {
161 ATH_MSG_ERROR("Failed at " << __LINE__ << " of getting SCT cluster shape info.");
162 }
163 auto cluster = dynamic_cast<const InDet::SCT_Cluster*>(cluster_1);
164 int barrel_endcap = m_SCT_ID->barrel_ec(cluster->identify());
165 switch (barrel_endcap) {
166 case -2:
167 region = 2;
168 break;
169 case 0:
170 region = 4;
171 break;
172 case 2:
173 region = 6;
174 break;
175 default:
176 ATH_MSG_ERROR("Unknown barrel_endcap: " << barrel_endcap);
177 break;
178 }
179 }
180 features["charge_count_1"] = charge_count_1;
181 features["count_1"] = pixel_count_1;
182 features["loc_eta_1"] = loc_eta_1;
183 features["loc_phi_1"] = loc_phi_1;
184 features["glob_eta_1"] = glob_eta_1;
185 features["glob_phi_1"] = glob_phi_1;
186 features["localDir0_1"] = localDir0_1;
187 features["localDir1_1"] = localDir1_1;
188 features["localDir2_1"] = localDir2_1;
189 features["lengthDir0_1"] = lengthDir0_1;
190 features["lengthDir1_1"] = lengthDir1_1;
191 features["lengthDir2_1"] = lengthDir2_1;
192 features["eta_angle_1"] = eta_angle_1;
193 features["phi_angle_1"] = phi_angle_1;
194 features["region"] = region;
195
196 if (isStrip) {
197 features["cluster_x_2"] = cluster_2->globalPosition().x();
198 features["cluster_y_2"] = cluster_2->globalPosition().y();
199 features["cluster_z_2"] = cluster_2->globalPosition().z();
200 features["cluster_r_2"] = std::sqrt(cluster_2->globalPosition().x() * cluster_2->globalPosition().x() + cluster_2->globalPosition().y() * cluster_2->globalPosition().y());
201 features["cluster_phi_2"] = std::atan2(cluster_2->globalPosition().y(), cluster_2->globalPosition().x());
202 features["cluster_eta_2"] = -1 * std::log(std::tan(0.5 * std::atan2(features["cluster_r_2"], features["cluster_z_2"])));
203 // the second cluster of the strip detector.
204 float charge_count_2 = 0;
205 int pixel_count_2 = 0;
206 float loc_eta_2 = 0, loc_phi_2 = 0; // clusterShape: [leta, lphi]
207 float glob_eta_2 = 0, glob_phi_2 = 0; // clusterShape: [geta, gphi]
208 float localDir0_2 = 0, localDir1_2 = 0, localDir2_2 = 0; // clusterShape: [lengthDir0, lengthDir1, lengthDir2]
209 float lengthDir0_2 = 0, lengthDir1_2 = 0, lengthDir2_2 = 0; // clusterShape: [lengthDir0, lengthDir1, lengthDir2]
210 float eta_angle_2 = 0, phi_angle_2 = 0;
211 auto status = getSCTClusterShapeInfo_fn(cluster_2, charge_count_2, pixel_count_2, loc_eta_2, loc_phi_2,
212 glob_eta_2, glob_phi_2,
213 localDir0_2, localDir1_2, localDir2_2,
214 lengthDir0_2, lengthDir1_2, lengthDir2_2,
215 eta_angle_2, phi_angle_2
216 );
217 if (status.isFailure()) {
218 ATH_MSG_ERROR("Failed at " << __LINE__ << " of getting SCT cluster shape info.");
219 }
220
221 features["charge_count_2"] = charge_count_2;
222 features["count_2"] = pixel_count_2;
223 features["loc_eta_2"] = loc_eta_2;
224 features["loc_phi_2"] = loc_phi_2;
225 features["glob_eta_2"] = glob_eta_2;
226 features["glob_phi_2"] = glob_phi_2;
227 features["localDir0_2"] = localDir0_2;
228 features["localDir1_2"] = localDir1_2;
229 features["localDir2_2"] = localDir2_2;
230 features["lengthDir0_2"] = lengthDir0_2;
231 features["lengthDir1_2"] = lengthDir1_2;
232 features["lengthDir2_2"] = lengthDir2_2;
233 features["eta_angle_2"] = eta_angle_2;
234 features["phi_angle_2"] = phi_angle_2;
235 } else {
236 // copy the cluster 1 to cluster 2.
237 features["cluster_x_2"] = features["cluster_x_1"];
238 features["cluster_y_2"] = features["cluster_y_1"];
239 features["cluster_z_2"] = features["cluster_z_1"];
240 features["cluster_r_2"] = features["cluster_r_1"];
241 features["cluster_phi_2"] = features["cluster_phi_1"];
242 features["cluster_eta_2"] = features["cluster_eta_1"];
243 features["charge_count_2"] = features["charge_count_1"];
244 features["count_2"] = features["count_1"];
245 features["loc_eta_2"] = features["loc_eta_1"];
246 features["loc_phi_2"] = features["loc_phi_1"];
247 features["glob_eta_2"] = features["glob_eta_1"];
248 features["glob_phi_2"] = features["glob_phi_1"];
249 features["localDir0_2"] = features["localDir0_1"];
250 features["localDir1_2"] = features["localDir1_1"];
251 features["localDir2_2"] = features["localDir2_1"];
252 features["lengthDir0_2"] = features["lengthDir0_1"];
253 features["lengthDir1_2"] = features["lengthDir1_1"];
254 features["lengthDir2_2"] = features["lengthDir2_1"];
255 features["eta_angle_2"] = features["eta_angle_1"];
256 features["phi_angle_2"] = features["phi_angle_1"];
257 }
258 return features;
259}
260
261
262void InDet::SpacepointFeatureTool::cartesion_to_spherical(const Amg::Vector3D &xyzVec, float &eta_, float &phi_) const {
263 float r3 = 0;
264 for (int idx = 0; idx < 3; ++idx) {
265 r3 += xyzVec[idx] * xyzVec[idx];
266 }
267 r3 = std::sqrt(r3);
268 phi_ = std::atan2(xyzVec[1], xyzVec[0]);
269 float theta_ = std::acos(xyzVec[2] / r3);
270 eta_ = std::log(std::tan(0.5 * theta_)); // a bug here, but keep it so it is consistent with the DumpObject.
271}
272
274 float &charge_count, int &pixel_count, float &loc_eta, float &loc_phi,
275 float &glob_eta, float &glob_phi,
276 float &localDir0, float &localDir1, float &localDir2,
277 float &lengthDir0, float &lengthDir1, float &lengthDir2,
278 float &eta_angle, float &phi_angle
279 ) const
280{
281 const InDet::SCT_Cluster* cluster = dynamic_cast<const InDet::SCT_Cluster*>(si_cluster);
282 const InDetDD::SiDetectorElement *element = cluster->detectorElement();
283 Amg::Vector2D locpos = cluster->localPosition();
284 std::pair<Amg::Vector3D, Amg::Vector3D> ends(
285 element->endsOfStrip(InDetDD::SiLocalPosition(locpos.y(), locpos.x(), 0)));
286 Amg::Vector3D JanDirection = ends.second - ends.first;
287 lengthDir0 = JanDirection[0];
288 lengthDir1 = JanDirection[1];
289 lengthDir2 = JanDirection[2];
290
291 // get local directions.
292 // retrieve cluster shape
293 const InDetDD::SCT_ModuleSideDesign *design(
294 dynamic_cast<const InDetDD::SCT_ModuleSideDesign *>(&element->design()));
295 if (not design) {
296 ATH_MSG_ERROR("Failed at " << __LINE__ << " of accessing SCT ModuleSide Design");
297 return StatusCode::FAILURE;
298 }
299
300 int min_strip = 999;
301 int max_strip = -999;
302
303 charge_count = 0;
304 pixel_count = 0;
305
306 for (unsigned int rdo = 0; rdo < cluster->rdoList().size(); rdo++) {
307 const auto &rdoID = cluster->rdoList().at(rdo);
308
309 int strip = m_SCT_ID->strip(rdoID);
310
311 if (min_strip > strip) min_strip = strip;
312 if (max_strip < strip) max_strip = strip;
313
314 ++pixel_count;
315 }
316
317 InDetDD::SiLocalPosition localPos_entry = design->localPositionOfCell(InDetDD::SiCellId(min_strip));
318 InDetDD::SiLocalPosition localPos_exit = design->localPositionOfCell(InDetDD::SiCellId(max_strip));
319
320 Amg::Vector3D localStartPosition(localPos_entry.xEta() - 0.5 * element->etaPitch(),
321 localPos_entry.xPhi() - 0.5 * element->phiPitch(),
322 -0.5 * element->thickness());
323 Amg::Vector3D localEndPosition(localPos_exit.xEta() + 0.5 * element->etaPitch(),
324 localPos_exit.xPhi() + 0.5 * element->phiPitch(), 0.5 * element->thickness());
325
326 Amg::Vector3D localDirection = localEndPosition - localStartPosition;
327 cartesion_to_spherical(localDirection, loc_eta, loc_phi);
328 localDir0 = localDirection[0];
329 localDir1 = localDirection[1];
330 localDir2 = localDirection[2];
331
332 Amg::Vector3D globalStartPosition = element->globalPosition(localStartPosition);
333 Amg::Vector3D globalEndPosition = element->globalPosition(localEndPosition);
334
335 Amg::Vector3D direction = globalEndPosition - globalStartPosition;
336 cartesion_to_spherical(direction, glob_eta, glob_phi);
337
338 Amg::Vector3D my_phiax = element->phiAxis();
339 Amg::Vector3D my_etaax = element->etaAxis();
340 Amg::Vector3D my_normal = element->normal();
341
342 float trkphicomp = direction.dot(my_phiax);
343 float trketacomp = direction.dot(my_etaax);
344 float trknormcomp = direction.dot(my_normal);
345 phi_angle = atan2(trknormcomp, trkphicomp);
346 eta_angle = atan2(trknormcomp, trketacomp);
347
348 return StatusCode::SUCCESS;
349}
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
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):
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