ATLAS Offline Software
Loading...
Searching...
No Matches
ClusterConversionUtilities.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
9
13#include "GeoModelKernel/throwExcept.h"
14
15constexpr static double one_over_twelve = 1. / 12.;
16
17namespace TrackingUtilities {
18
19 std::pair<xAOD::MeasVector<3>, xAOD::MeasMatrix<3>> convertHGTD_LocalPosCov(const HGTD_Cluster &cluster) {
20 auto localPos = cluster.localPosition();
21 auto localCov = cluster.localCovariance();
22
23 const float time = cluster.time();
24 const float timeResolution = cluster.timeResolution();
25
26 Eigen::Matrix<float,3,1> localPosition = Eigen::Matrix<float,3,1>::Zero();
27 localPosition(0, 0) = localPos.x();
28 localPosition(1, 0) = localPos.y();
29 localPosition(2, 0) = time;
30
31 Eigen::Matrix<float,3,3> localCovariance = Eigen::Matrix<float,3,3>::Zero();
32 localCovariance(0, 0) = localCov(0, 0);
33 localCovariance(1, 1) = localCov(1, 1);
34 localCovariance(2, 2) = timeResolution * timeResolution;
35
36 return {localPosition, localCovariance};
37 }
38
39 StatusCode convertInDetToXaodCluster(const HGTD_Cluster& indetCluster,
40 const InDetDD::HGTD_DetectorElement& element,
41 xAOD::HGTDCluster& xaodCluster)
42 {
43 IdentifierHash idHash = element.identifyHash();
44
45 const auto [localPosition, localCovariance] = convertHGTD_LocalPosCov(indetCluster);
46
47 const auto& RDOs = indetCluster.rdoList();
48 const auto& ToTs = indetCluster.totList();
49
50 xaodCluster.setMeasurement<3>(idHash, localPosition, localCovariance);
51 xaodCluster.setIdentifier( indetCluster.identify().get_compact() );
52 xaodCluster.setRDOlist(RDOs);
53 xaodCluster.setToTlist(ToTs);
54
55 return StatusCode::SUCCESS;
56 }
57
58 std::pair<xAOD::MeasVector<2>, xAOD::MeasMatrix<2>> convertPix_LocalPosCov(const InDet::PixelCluster &cluster) {
59 auto localPos = cluster.localPosition();
60 auto localCov = cluster.localCovariance();
61
62 Eigen::Matrix<float,2,1> localPosition(localPos.x(), localPos.y());
63
64 Eigen::Matrix<float,2,2> localCovariance;
65 localCovariance.setZero();
66 localCovariance(0, 0) = localCov(0, 0);
67 localCovariance(1, 1) = localCov(1, 1);
68
69 return {localPosition, localCovariance};
70 }
71
72 StatusCode convertInDetToXaodCluster(const InDet::PixelCluster& indetCluster,
73 const InDetDD::SiDetectorElement& element,
74 xAOD::PixelCluster& xaodCluster)
75 {
76 IdentifierHash idHash = element.identifyHash();
77
78 const auto [localPosition, localCovariance] = convertPix_LocalPosCov(indetCluster);
79
80 auto globalPos = indetCluster.globalPosition();
81 Eigen::Matrix<float, 3, 1> globalPosition(globalPos.x(), globalPos.y(), globalPos.z());
82
83 const auto& RDOs = indetCluster.rdoList();
84 const auto& ToTs = indetCluster.totList();
85 const auto& charges = indetCluster.chargeList();
86 const auto& width = indetCluster.width();
87
88 xaodCluster.setMeasurement<2>(idHash, localPosition, localCovariance);
89 xaodCluster.setIdentifier( indetCluster.identify().get_compact() );
90 xaodCluster.setRDOlist(RDOs);
91 xaodCluster.globalPosition() = globalPosition;
92 xaodCluster.setToTlist(ToTs);
93 xaodCluster.setChargelist(charges);
94 xaodCluster.setLVL1A(indetCluster.LVL1A());
95 xaodCluster.setChannelsInPhiEta(width.colRow()[0], width.colRow()[1]);
96 xaodCluster.setWidthInEta(static_cast<float>(width.widthPhiRZ()[1]));
97
98 return StatusCode::SUCCESS;
99 }
100
101 std::pair<xAOD::MeasVector<1>, xAOD::MeasMatrix<1>> convertSCT_LocalPosCov(const InDet::SCT_Cluster &cluster, bool isITk) {
102 const InDetDD::SiDetectorElement& element{*cluster.detectorElement()};
103 auto localPos = cluster.localPosition();
104
105 float localPosition = 0.f, localCovariance = 0.f;
106 if (element.isBarrel() or (not isITk)) {
107 localPosition = localPos.x();
108 localCovariance = element.phiPitch() * element.phiPitch() * one_over_twelve;
109 } else {
110 InDetDD::SiCellId cellId = element.cellIdOfPosition(localPos);
111 const auto* design = dynamic_cast<const InDetDD::StripStereoAnnulusDesign *>(&element.design());
112 if ( design == nullptr ) {
113 THROW_EXCEPTION("Invalid bounds from "<<cluster);
114 }
115 InDetDD::SiLocalPosition localInPolar = design->localPositionOfCellPC(cellId);
116 localPosition = localInPolar.xPhi();
117 localCovariance = design->phiPitchPhi() * design->phiPitchPhi() * one_over_twelve;
118 }
119
120 return std::make_pair(xAOD::MeasVector<1>{localPosition},
121 xAOD::MeasMatrix<1>{localCovariance});
122 }
123
124 StatusCode convertInDetToXaodCluster(const InDet::SCT_Cluster& indetCluster,
125 const InDetDD::SiDetectorElement& element,
126 xAOD::StripCluster& xaodCluster,
127 bool isITk)
128 {
129 IdentifierHash idHash = element.identifyHash();
130
131 const auto [localPosition, localCovariance] = convertSCT_LocalPosCov(indetCluster, isITk);
132
133 auto globalPos = indetCluster.globalPosition();
134 Eigen::Matrix<float, 3, 1> globalPosition(globalPos.x(), globalPos.y(), globalPos.z());
135
136 const auto& RDOs = indetCluster.rdoList();
137 const auto& width = indetCluster.width();
138
139 xaodCluster.setMeasurement<1>(idHash, localPosition, localCovariance);
140 xaodCluster.setIdentifier( indetCluster.identify().get_compact() );
141 xaodCluster.setRDOlist(RDOs);
142 xaodCluster.globalPosition() = globalPosition;
143 xaodCluster.setChannelsInPhi(width.colRow()[0]);
144
145 return StatusCode::SUCCESS;
146 }
147
148 StatusCode convertXaodToInDetCluster(const xAOD::PixelCluster& xaodCluster,
149 const InDetDD::SiDetectorElement& element,
150 const PixelID& pixelID,
151 InDet::PixelCluster*& indetCluster)
152 {
153 const InDetDD::PixelModuleDesign* design(dynamic_cast<const InDetDD::PixelModuleDesign*>(&element.design()));
154 if (design == nullptr) {
155 return StatusCode::FAILURE;
156 }
157
158 const auto& locPos = xaodCluster.localPosition<2>();
159 Amg::Vector2D localPosition(locPos(0,0), locPos(1,0));
160
161 InDetDD::SiLocalPosition centroid(localPosition);
162 const Identifier id = element.identifierOfPosition(centroid);
163
164 const auto& globalPos = xaodCluster.globalPosition();
165 Amg::Vector3D globalPosition(globalPos(0, 0), globalPos(1, 0), globalPos(2, 0));
166
167 auto errorMatrix = Amg::MatrixX(2,2);
168 errorMatrix.setIdentity();
169 errorMatrix.fillSymmetric(0, 0, xaodCluster.localCovariance<2>()(0, 0));
170 errorMatrix.fillSymmetric(1, 1, xaodCluster.localCovariance<2>()(1, 1));
171
172 int colmax = std::numeric_limits<int>::min();
173 int rowmax = std::numeric_limits<int>::min();
174 int colmin = std::numeric_limits<int>::max();
175 int rowmin = std::numeric_limits<int>::max();
176
177 float qRowMin = 0.f;
178 float qRowMax = 0.f;
179 float qColMin = 0.f;
180 float qColMax = 0.f;
181
182 const std::vector<Identifier>& rod_list_cluster = xaodCluster.rdoList();
183 const std::vector<float>& charge_list_cluster = xaodCluster.chargeList();
184
185 if (rod_list_cluster.size() == charge_list_cluster.size()) {
186
187 for (std::size_t i(0); i<rod_list_cluster.size(); ++i) {
188 const Identifier& this_rdo = rod_list_cluster[i];
189 const float this_charge = charge_list_cluster[i];
190
191 const int row = pixelID.phi_index(this_rdo);
192 if (row > rowmax) {
193 rowmax = row;
194 qRowMax = this_charge;
195 } else if (row == rowmax) {
196 qRowMax += this_charge;
197 }
198
199 if (row < rowmin) {
200 rowmin = row;
201 qRowMin = this_charge;
202 } else if (row == rowmin) {
203 qRowMin += this_charge;
204 }
205
206 const int col = pixelID.eta_index(this_rdo);
207 if (col > colmax) {
208 colmax = col;
209 qColMax = this_charge;
210 } else if (col == colmax) {
211 qColMax += this_charge;
212 }
213
214 if (col < colmin) {
215 colmin = col;
216 qColMin = this_charge;
217 } else if (col == colmin) {
218 qColMin += this_charge;
219 }
220
221 }//loop on rdo list
222 } // check that rdo list has the same size of charge list
223
224 // Compute omega for charge interpolation correction (if required)
225 // Two pixels may have charge=0 (very rarely, hopefully)
226 float omegax = -1.f;
227 float omegay = -1.f;
228 if(qRowMin + qRowMax > 0) omegax = qRowMax/(qRowMin + qRowMax);
229 if(qColMin + qColMax > 0) omegay = qColMax/(qColMin + qColMax);
230
231 double etaWidth = design->widthFromColumnRange(colmin, colmax);
232 double phiWidth = design->widthFromRowRange(rowmin, rowmax);
233 InDet::SiWidth width( Amg::Vector2D(xaodCluster.channelsInPhi(), xaodCluster.channelsInEta()),
234 Amg::Vector2D(phiWidth,etaWidth) );
235
236 indetCluster = new InDet::PixelCluster(id,
237 localPosition,
238 globalPosition,
239 std::vector<Identifier>(xaodCluster.rdoList()),
240 xaodCluster.lvl1a(),
241 std::vector<int>(xaodCluster.totList()),
242 std::vector<float>(xaodCluster.chargeList()),
243 width,
244 &element,
245 std::move(errorMatrix),
246 omegax,
247 omegay,
248 false, 0, 0);
249
250 return StatusCode::SUCCESS;
251 }
252
253 StatusCode convertXaodToInDetCluster(const xAOD::StripCluster& xaodCluster,
254 const InDetDD::SiDetectorElement& element,
255 const SCT_ID& stripID,
256 InDet::SCT_Cluster*& indetCluster,
257 double shift)
258 {
259 bool isBarrel = element.isBarrel();
260 const InDetDD::SCT_ModuleSideDesign* design = nullptr;
261 if (not isBarrel) {
262 design = dynamic_cast<const InDetDD::StripStereoAnnulusDesign*>(&element.design());
263 } else {
264 design = dynamic_cast<const InDetDD::SCT_ModuleSideDesign*>(&element.design());
265 }
266
267 if (design == nullptr) {
268 return StatusCode::FAILURE;
269 }
270
271 const auto designShape = design->shape();
272
273
274 const auto& rdoList = xaodCluster.rdoList();
275 Identifier id = rdoList.front();
276
277 const auto& localPos = xaodCluster.localPosition<1>();
278
279 double pos_x = localPos(0, 0);
280 double pos_y = 0;
281 if (not isBarrel) {
282 const Identifier firstStripId = rdoList.front();
283 int firstStrip = stripID.strip(firstStripId);
284 int stripRow = stripID.row(firstStripId);
285 int clusterSizeInStrips = xaodCluster.channelsInPhi();
286 auto clusterPosition = design->localPositionOfCluster(design->strip1Dim(firstStrip, stripRow), clusterSizeInStrips);
287 pos_x = clusterPosition.xPhi() + shift;
288 pos_y = clusterPosition.xEta();
289 }
290
291 Amg::Vector2D locpos = Amg::Vector2D( pos_x, pos_y );
292
293 // Most of the following is taken from what is done in ClusterMakerTool
294 // Need to make this computation instead of using the local pos
295 // with local pos instead some differences w.r.t. reference are observed
296 const auto& firstStrip = stripID.strip(rdoList.front());
297 const auto& lastStrip = stripID.strip(rdoList.back());
298 const auto& row = stripID.row(rdoList.front());
299 const int firstStrip1D = design->strip1Dim (firstStrip, row );
300 const int lastStrip1D = design->strip1Dim( lastStrip, row );
301 const InDetDD::SiCellId cell1(firstStrip1D);
302 const InDetDD::SiCellId cell2(lastStrip1D);
303 const InDetDD::SiLocalPosition firstStripPos( element.rawLocalPositionOfCell(cell1 ));
304 const InDetDD::SiLocalPosition lastStripPos( element.rawLocalPositionOfCell(cell2) );
305 const InDetDD::SiLocalPosition centre( (firstStripPos+lastStripPos) * 0.5 );
306 const double clusterWidth = design->stripPitch() * ( lastStrip - firstStrip + 1 );
307
308 const std::pair<InDetDD::SiLocalPosition, InDetDD::SiLocalPosition> ends( design->endsOfStrip(centre) );
309 const double stripLength( std::abs(ends.first.xEta() - ends.second.xEta()) );
310
312 Amg::Vector2D(clusterWidth, stripLength) );
313
314 const double col_x = width.colRow().x();
315 const double col_y = width.colRow().y();
316
317 double scale_factor = 1.;
318 if ( col_x == 1 )
319 scale_factor = 1.05;
320 else if ( col_x == 2 )
321 scale_factor = 0.27;
322
323 auto errorMatrix = Amg::MatrixX(2,2);
324 errorMatrix.setIdentity();
325 errorMatrix.fillSymmetric(0, 0, scale_factor * scale_factor * width.phiR() * width.phiR() * one_over_twelve);
326 errorMatrix.fillSymmetric(1, 1, width.z() * width.z() / col_y / col_y * one_over_twelve);
327
328 if( designShape == InDetDD::Trapezoid or
329 designShape == InDetDD::Annulus) {
330 // rotation for endcap SCT
331
332 // The following is being computed with the local position,
333 // without considering the lorentz shift
334 // So we remove it from the local position
335 Amg::Vector2D local(pos_x - shift, pos_y);
336 double sn = element.sinStereoLocal(local);
337 double sn2 = sn * sn;
338 double cs2 = 1. - sn2;
339 double w = element.phiPitch(local) / element.phiPitch();
340 double v0 = errorMatrix(0,0) * w * w;
341 double v1 = errorMatrix(1,1);
342 errorMatrix.fillSymmetric( 0, 0, cs2 * v0 + sn2 * v1 );
343 errorMatrix.fillSymmetric( 0, 1, sn * std::sqrt(cs2) * (v0 - v1) );
344 errorMatrix.fillSymmetric( 1, 1, sn2 * v0 + cs2 * v1 );
345 }
346
347 indetCluster = new InDet::SCT_Cluster(id,
348 locpos,
349 std::vector<Identifier>(rdoList),
350 width,
351 &element,
352 std::move(errorMatrix));
353
354 return StatusCode::SUCCESS;
355 }
356
357 StatusCode convertXaodToInDetCluster(const xAOD::HGTDCluster& xaodCluster,
358 const InDetDD::HGTD_DetectorElement& element,
359 ::HGTD_Cluster*& indetCluster) {
360
361 const auto& locPos = xaodCluster.localPosition<3>();
362 Amg::Vector2D localPosition(locPos(0,0), locPos(1,0));
363 float time = locPos(2,0);
364
365 InDetDD::SiLocalPosition centroid(localPosition);
366 const Identifier id = element.identifierOfPosition(centroid);
367
368 auto errorMatrix = Amg::MatrixX(2,2);
369 errorMatrix.setIdentity();
370 errorMatrix.fillSymmetric(0, 0, xaodCluster.localCovariance<3>()(0, 0));
371 errorMatrix.fillSymmetric(1, 1, xaodCluster.localCovariance<3>()(1, 1));
372 float time_resolution = std::sqrt(xaodCluster.localCovariance<3>()(2, 2));
373
374 double etaWidth = 1.3;
375 double phiWidth = 1.3;
376 int channelsPhi = 1;
377 int channelsEta = 1;
378 InDet::SiWidth width( Amg::Vector2D(channelsPhi, channelsEta), Amg::Vector2D(phiWidth, etaWidth) );
379
380 indetCluster = new ::HGTD_Cluster(id,
381 localPosition,
382 std::vector<Identifier>(xaodCluster.rdoList()),
383 width,
384 &element,
385 std::move(errorMatrix),
386 time,
387 time_resolution,
388 std::vector<int>(xaodCluster.totList()));
389
390 return StatusCode::SUCCESS;
391 }
392
393} // Namespace
394
395
static constexpr double one_over_twelve
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
const double width
virtual float time() const
virtual const std::vector< int > & totList() const
virtual float timeResolution() const
This is a "hash" representation of an Identifier.
value_type get_compact() const
Get the compact id.
virtual DetectorShape shape() const
Shape of element.
Class to hold geometrical description of an HGTD detector element.
Class used to describe the design of a module (diode segmentation and readout scheme)
double widthFromRowRange(const int rowMin, const int rowMax) const
Method to calculate phi width from a row range.
double widthFromColumnRange(const int colMin, const int colMax) const
Method to calculate eta width from a column range.
Base class for the SCT module side design, extended by the Forward and Barrel module design.
virtual double stripPitch(const SiLocalPosition &chargePos) const =0
give the strip pitch (dependence on position needed for forward)
virtual int strip1Dim(int strip, int row) const override
only relevant for SCT.
virtual SiLocalPosition localPositionOfCluster(const SiCellId &cellId, int cluserSize) const =0
virtual std::pair< SiLocalPosition, SiLocalPosition > endsOfStrip(const SiLocalPosition &position) const override=0
give the ends of strips
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
double phiPitch() const
Pitch (inline methods)
double sinStereoLocal(const Amg::Vector2D &localPos) const
Angle of strip in local frame with respect to the etaAxis.
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:
SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const
As in previous method but returns SiCellId.
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
Identifier identifierOfPosition(const Amg::Vector2D &localPos) const
Full identifier of the cell for a given position: assumes a raw local position (no Lorentz shift)
Amg::Vector2D rawLocalPositionOfCell(const SiCellId &cellId) const
Returns position (center) of cell.
const Amg::Vector3D & globalPosition() const
return global position reference
const InDet::SiWidth & width() const
return width class 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...
This is an Identifier helper class for the Pixel subdetector.
Definition PixelID.h:69
int eta_index(const Identifier &id) const
Definition PixelID.h:640
int phi_index(const Identifier &id) const
Definition PixelID.h:634
This is an Identifier helper class for the SCT subdetector.
Definition SCT_ID.h:68
int row(const Identifier &id) const
Definition SCT_ID.h:711
int strip(const Identifier &id) const
Definition SCT_ID.h:717
const Amg::Vector2D & localPosition() const
return the local position reference
Identifier identify() const
return the identifier
const Amg::MatrixX & localCovariance() const
return const ref to the error matrix
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
const std::vector< int > & totList() const
Returns the list of Time Over Threshold of the channels building the cluster.
void setToTlist(const std::vector< int > &tots)
Sets the list of ToT of the channels building the cluster.
const std::vector< Identifier > rdoList() const
Returns the list of identifiers of the channels building the cluster.
void setRDOlist(const std::vector< Identifier > &rdolist)
Sets the list of identifiers of the channels building the cluster.
const std::vector< float > & chargeList() const
Returns the list of charges of the channels building the cluster.
const std::vector< int > & totList() const
Returns the list of ToT of the channels building the cluster.
void setChannelsInPhiEta(int channelsInPhi, int channelsInEta)
Sets the dimensions of the cluster in numbers of channels in phi (x) and eta (y) directions.
int channelsInPhi() const
Returns the dimensions of the cluster in numbers of channels in phi (x) and eta (y) directions,...
const std::vector< Identifier > rdoList() const
Returns the list of identifiers of the channels building the cluster.
ConstVectorMap< 3 > globalPosition() const
Returns the global position of the pixel cluster.
int lvl1a() const
Return the LVL1 accept.
void setChargelist(const std::vector< float > &charges)
Sets the list of charges of the channels building the cluster.
int channelsInEta() const
void setToTlist(const std::vector< int > &tots)
Sets the list of ToT of the channels building the cluster.
void setLVL1A(int lvl1a)
Sets the LVL1 accept.
void setRDOlist(const std::vector< Identifier > &rdolist)
Sets the list of identifiers of the channels building the cluster.
void setWidthInEta(float widthInEta)
Sets the width of the cluster in eta (y) direction.
ConstVectorMap< 3 > globalPosition() const
Returns the global position of the strip cluster.
void setRDOlist(const std::vector< Identifier > &rdolist)
Sets the list of identifiers of the channels building the cluster.
int channelsInPhi() const
Returns the dimensions of the cluster in numbers of channels in phi (x), respectively.
const std::vector< Identifier > rdoList() const
Returns the list of identifiers of the channels building the cluster.
void setChannelsInPhi(int channelsInPhi)
Sets the dimensions of the cluster in numbers of channels in phi (x)
void setMeasurement(const DetectorIDHashType idHash, MeasVector< N > locPos, MeasMatrix< N > locCov)
Sets IdentifierHash, local position and local covariance of the measurement.
ConstMatrixMap< N > localCovariance() const
Returns the local covariance of the measurement.
ConstVectorMap< N > localPosition() const
Returns the local position of the measurement.
void setIdentifier(const DetectorIdentType measId)
Sets the full Identifier of the measurement.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
std::pair< xAOD::MeasVector< 1 >, xAOD::MeasMatrix< 1 > > convertSCT_LocalPosCov(const InDet::SCT_Cluster &cluster, bool isITk=true)
std::pair< xAOD::MeasVector< 2 >, xAOD::MeasMatrix< 2 > > convertPix_LocalPosCov(const InDet::PixelCluster &cluster)
StatusCode convertXaodToInDetCluster(const xAOD::PixelCluster &xaodCluster, const InDetDD::SiDetectorElement &element, const PixelID &pixelID, InDet::PixelCluster *&indetCluster)
StatusCode convertInDetToXaodCluster(const InDet::PixelCluster &indetCluster, const InDetDD::SiDetectorElement &element, xAOD::PixelCluster &xaodCluster)
std::pair< xAOD::MeasVector< 3 >, xAOD::MeasMatrix< 3 > > convertHGTD_LocalPosCov(const HGTD_Cluster &cluster)
StripCluster_v1 StripCluster
Define the version of the strip cluster class.
Eigen::Matrix< float, N, N > MeasMatrix
Eigen::Matrix< float, N, 1 > MeasVector
Abrivation of the Matrix & Covariance definitions.
PixelCluster_v1 PixelCluster
Define the version of the pixel cluster class.
HGTDCluster_v1 HGTDCluster
Define the version of the pixel cluster class.
Definition HGTDCluster.h:13
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10