ATLAS Offline Software
Loading...
Searching...
No Matches
TracccMeasurementConverterAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
5
8
12
13#include "TrkSurfaces/Surface.h"
14
15#include <stdexcept>
16
17namespace ActsTrk {
18
20{
21 ATH_MSG_DEBUG("Initializing.");
22
23 ATH_CHECK(m_hostMR.retrieve());
24 ATH_CHECK(m_copy.retrieve());
25
26 ATH_CHECK(m_inputMeasKey.initialize());
29
30 ATH_CHECK(m_outputPixelKey.initialize());
31 ATH_CHECK(m_outputStripKey.initialize());
32
34 ATH_CHECK(detStore()->retrieve(m_stripID, "SCT_ID"));
35 ATH_CHECK(detStore()->retrieve(m_pixelManager, "ITkPixel"));
36 ATH_CHECK(detStore()->retrieve(m_stripManager, "ITkStrip"));
37
38 m_detrayToAthena = &m_detDescSvc->detrayToAthenaMap();
39
40 ATH_MSG_DEBUG("Successfully initialized");
41 return StatusCode::SUCCESS;
42}
43
45std::pair<int, int> countPixelStrip(
46 const traccc::edm::measurement_collection::const_device& measurements) {
47 int n_pixels = 0;
48 int n_strips = 0;
49 for (std::size_t i = 0; i < measurements.size(); ++i) {
50 if (measurements.at(i).dimensions() == 2u) {
51 ++n_pixels;
52 } else {
53 ++n_strips;
54 }
55 }
56 return {n_pixels, n_strips};
57}
58
59// Allocate `n` clusters from the pool into a view container + aux store.
60template <typename ClusterT, typename AuxContainerT,
61 typename ContainerT = DataVector<ClusterT>>
62 std::pair<std::unique_ptr<ContainerT>, std::unique_ptr<AuxContainerT>>
63 makeOutputContainer(const EventContext& ctx, int n) {
64
66
67 auto cont = std::make_unique<ContainerT>(SG::VIEW_ELEMENTS,
69 auto aux = std::make_unique<AuxContainerT>();
70
71 pool.reserve(n);
72 cont->push_new(n, [&pool]() { return pool.nextElementPtr(); });
73 aux->resize(cont->size());
74 cont->setStore(aux.get());
75
76 return {std::move(cont), std::move(aux)};
77}
78
79template <typename MEAS>
80void fillStripCluster(const MEAS& meas, const Identifier& athenaId,
81 const SCT_ID* stripID,
82 const InDetDD::SCT_DetectorManager* stripManager,
83 xAOD::StripCluster& xaod_scl,
84 std::size_t combinedIndex) {
85 const IdentifierHash stripHash = stripID->wafer_hash(athenaId);
87 stripManager->getDetectorElement(stripHash);
88
89 Eigen::Matrix<float, 1, 1> localPosition = Eigen::Matrix<float, 1, 1>::Zero();
90 Eigen::Matrix<float, 1, 1> localCovariance =
91 Eigen::Matrix<float, 1, 1>::Zero();
92
93 if (pDE->isBarrel()) {
94 localPosition(0, 0) = meas.local_position()[0];
95 localCovariance(0, 0) = meas.local_variance()[0];
96 } else {
97 localPosition(0, 0) = meas.local_position()[1];
98 localCovariance(0, 0) = meas.local_variance()[1];
99 }
100
101 const Identifier hitId(athenaId.get_compact() + combinedIndex);
102
103 xaod_scl.setMeasurement<1>(stripHash, localPosition, localCovariance);
104 xaod_scl.setIdentifierHash(stripHash);
105 xaod_scl.setIdentifier(hitId.get_compact());
106}
107
108template <typename MEAS>
109void fillPixelCluster(const MEAS& meas, const Identifier& athenaId,
110 const PixelID* pixelID,
111 const InDetDD::PixelDetectorManager* pixelManager,
112 xAOD::PixelCluster& xaod_pcl,
113 std::size_t combinedIndex) {
114 const IdentifierHash pixHash = pixelID->wafer_hash(athenaId);
115 const InDetDD::SiDetectorElement* pDE =
116 pixelManager->getDetectorElement(pixHash);
117
118 const Amg::Vector2D localPos(meas.local_position()[0],
119 meas.local_position()[1]);
120 const Amg::Vector3D gp = pDE->globalPosition(localPos);
121
122 Eigen::Matrix<float, 2, 1> localPosition(localPos.x(), localPos.y());
123 Eigen::Matrix<float, 2, 2> localCovariance =
124 Eigen::Matrix<float, 2, 2>::Zero();
125 localCovariance(0, 0) = meas.local_variance()[0];
126 localCovariance(1, 1) = meas.local_variance()[1];
127
128 const Identifier hitId(athenaId.get_compact() + combinedIndex);
129
130 xaod_pcl.setIdentifierHash(pixHash);
131 xaod_pcl.setMeasurement<2>(pixHash, localPosition, localCovariance);
132 xaod_pcl.globalPosition() = Eigen::Matrix<float, 3, 1>(gp.x(), gp.y(), gp.z());
133 xaod_pcl.setIdentifier(hitId.get_compact());
134 xaod_pcl.setWidthInEta(meas.diameter());
135}
136
137StatusCode TracccMeasurementConverterAlg::execute(const EventContext& ctx) const
138{
139 // ---- Retrieve measurements (always needed) ----
140 auto measurements = SG::makeHandle(m_inputMeasKey, ctx);
141 ATH_CHECK(measurements.isValid());
142
143 auto copy = m_copy->copy(ctx);
144
145 traccc::edm::measurement_collection::buffer traccc_measurements_buffer{
146 copy->get_size(*measurements), m_hostMR->mr()};
147 copy->setup(traccc_measurements_buffer)->ignore();
148 (*copy)(*measurements, traccc_measurements_buffer)->wait();
149
150 traccc::edm::measurement_collection::const_device traccc_measurements(
151 traccc_measurements_buffer);
152
153 // ---- Optionally retrieve clusters and cells ----
154 std::optional<traccc::edm::silicon_cluster_collection::buffer> traccc_clusters_buffer;
155 std::optional<traccc::edm::silicon_cell_collection::buffer> traccc_cells_buffer;
156 std::optional<traccc::edm::silicon_cluster_collection::const_device> traccc_clusters;
157 std::optional<traccc::edm::silicon_cell_collection::const_device> traccc_cells;
158
160 ATH_MSG_DEBUG("Read " << traccc_measurements.size() << " traccc measurements from " << m_inputMeasKey.key());
161 ATH_MSG_DEBUG("Read traccc clusters from '"
162 << m_inputClusterKey.key()
163 << "' and will convert them with associated cells.");
164
166 m_inputClusterKey, ctx};
167 ATH_CHECK(clusters.isValid());
169 m_inputCellsKey, ctx};
170 ATH_CHECK(cells.isValid());
171
172 traccc_clusters_buffer.emplace(copy->get_sizes(*clusters), m_hostMR->mr());
173 copy->setup(*traccc_clusters_buffer)->wait();
174 (*copy)(*clusters, *traccc_clusters_buffer)->wait();
175
176 traccc_cells_buffer.emplace(copy->get_size(*cells), m_hostMR->mr());
177 copy->setup(*traccc_cells_buffer)->wait();
178 (*copy)(*cells, *traccc_cells_buffer)->wait();
179
180 traccc_clusters.emplace(*traccc_clusters_buffer);
181 ATH_MSG_DEBUG("Copied " << traccc_clusters->size() << " clusters.");
182
183 traccc_cells.emplace(*traccc_cells_buffer);
184 ATH_MSG_DEBUG("Copied " << traccc_cells->size() << " cells.");
185 } else {
186 ATH_MSG_DEBUG("Read traccc measurements from '"
187 << m_inputMeasKey.key()
188 << "' and will convert them without associated cells.");
189 }
190
191 // ---- Count pixel vs strip ----
192 const auto [n_pixels, n_strips] = countPixelStrip(traccc_measurements);
193
194 // ---- Create output containers ----
195 auto [pixel_cont, pixel_aux] =
197 auto [strip_cont, strip_aux] =
199
200 // ---- Convert ----
201 auto pixItr = pixel_cont->begin();
202 auto stripItr = strip_cont->begin();
203
204 std::size_t pixel_idx = 0;
205 std::size_t strip_idx = 0;
206
207 for (std::size_t i = 0; i < traccc_measurements.size(); ++i) {
208 const auto& meas = traccc_measurements.at(i);
209 const uint64_t detrayId = meas.surface_link().value();
210 const Identifier athenaId = m_detrayToAthena->at(detrayId);
211
212 // ---- Pixel ----
213 if (meas.dimensions() == 2u) {
214 xAOD::PixelCluster* xaod_pcl = *pixItr;
215 ++pixItr;
216
217 // once seeding will come into play, we will need to keep track of the
218 // mapping between traccc and xAOD clusters. The reason for this is
219 // because the traccc measurements are all in one collection, and the
220 // xAOD clusters are in two separate collections (pixel and strip)
221 // if (traccc_to_xaod_cluster_map != nullptr) {
222 // (*traccc_to_xaod_cluster_map)[meas.identifier()] = pixel_idx;
223 // }
224
225 const IdentifierHash Pixel_ModuleHash =
226 m_pixelID->wafer_hash(athenaId);
227 const InDetDD::SiDetectorElement* pDE =
228 m_pixelManager->getDetectorElement(Pixel_ModuleHash);
229 const InDetDD::PixelModuleDesign* design(
230 dynamic_cast<const InDetDD::PixelModuleDesign*>(
231 &pDE->design()));
232 if(design == nullptr){
233 ATH_MSG_FATAL("Could not retrieve module design for pixel module hash " << Pixel_ModuleHash);
234 return StatusCode::FAILURE;
235 }
236
237 fillPixelCluster(meas, athenaId, m_pixelID, m_pixelManager, *xaod_pcl,
238 pixel_idx + strip_idx);
239
241 const auto cluster = traccc_clusters->at(meas.cluster_index());
242
243 std::vector<Identifier> rdoList;
244 rdoList.reserve(cluster.cell_indices().size());
245 int phiIndicesMax = -1;
246 int etaIndicesMax = -1;
247 int phiIndicesMin = std::numeric_limits<int>::max();
248 int etaIndicesMin = std::numeric_limits<int>::max();
249
250 for (const unsigned int cell_idx : cluster.cell_indices()) {
251 const auto& cell = traccc_cells->at(cell_idx);
252
253 int const phiIndex = cell.channel0();
254 int const etaIndex = cell.channel1();
255
256 phiIndicesMax = std::max(phiIndicesMax, phiIndex);
257 etaIndicesMax = std::max(etaIndicesMax, etaIndex);
258 phiIndicesMin = std::min(phiIndicesMin, phiIndex);
259 etaIndicesMin = std::min(etaIndicesMin, etaIndex);
260
261 Identifier const hit_id =
262 m_pixelID->pixel_id(athenaId, phiIndex, etaIndex);
263 rdoList.push_back(hit_id);
264 }
265
266 double const colWidth = static_cast<double>((etaIndicesMax - etaIndicesMin) + 1);
267 double const rowWidth = static_cast<double>((phiIndicesMax - phiIndicesMin) + 1);
268 double const etaWidth =
269 design->widthFromColumnRange(etaIndicesMin, etaIndicesMax);
270 double const phiWidth = design->widthFromRowRange(phiIndicesMin, phiIndicesMax);
271
272 InDet::SiWidth siWidth(Amg::Vector2D(rowWidth, colWidth),
273 Amg::Vector2D(phiWidth, etaWidth));
274
275 float width0 = phiWidth / rowWidth;
276 float width1 = etaWidth / colWidth;
277 Eigen::Matrix<float, 2, 2> localCovariance =
278 Eigen::Matrix<float, 2, 2>::Zero();
279 localCovariance(0, 0) = width0 * width0 / 12.0f;
280 localCovariance(1, 1) = width1 * width1 / 12.0f;
281
282 Eigen::Matrix<float, 2, 1> localPosition(meas.local_position()[0], meas.local_position()[1]);
283 xaod_pcl->setMeasurement<2>(Pixel_ModuleHash, localPosition,
284 localCovariance);
285
286 std::sort(rdoList.begin(), rdoList.end());
287 xaod_pcl->setIdentifier(rdoList.front().get_compact());
288 xaod_pcl->setRDOlist(std::move(rdoList));
289 xaod_pcl->setChannelsInPhiEta(siWidth.colRow()[0],
290 siWidth.colRow()[1]);
291 float width_phiRZ = static_cast<float>(siWidth.widthPhiRZ()[1]);
292 xaod_pcl->setWidthInEta(width_phiRZ);
293
294 }
295 ++pixel_idx;
296
297 // ---- Strip ----
298 } else {
299 xAOD::StripCluster* xaod_scl = *stripItr;
300 ++stripItr;
301
302 // see comment above for pixel clusters, the same applies here
303 // if (traccc_to_xaod_cluster_map != nullptr) {
304 // (*traccc_to_xaod_cluster_map)[meas.identifier()] = strip_idx;
305 // }
306 const IdentifierHash Strip_ModuleHash =
307 m_stripID->wafer_hash(athenaId);
308 const InDetDD::SiDetectorElement* pDE =
309 m_stripManager->getDetectorElement(Strip_ModuleHash);
310
311 fillStripCluster(meas, athenaId, m_stripID, m_stripManager, *xaod_scl,
312 pixel_idx + strip_idx);
313
315 const auto cluster = traccc_clusters->at(meas.cluster_index());
316
317 std::vector<Identifier> rdoList;
318 rdoList.reserve(cluster.cell_indices().size());
319 int phiIndicesMax = -1;
320 int phiIndicesMin = std::numeric_limits<int>::max();
321
322 for (const unsigned int cell_idx : cluster.cell_indices()) {
323 const auto& cell = traccc_cells->at(cell_idx);
324
325 // (m_stripID->barrel_ec(athenaId) != 0) <=> endcap strip
326 // => we are working with polar coordinates (r,phi)
327 // and we have to swap the indices
328 int const phiIndex = (m_stripID->barrel_ec(athenaId) != 0)
329 ? cell.channel1()
330 : cell.channel0();
331
332 phiIndicesMax = std::max(phiIndicesMax, phiIndex);
333 phiIndicesMin = std::min(phiIndicesMin, phiIndex);
334 Identifier const hit_id =
335 m_stripID->strip_id(athenaId, int(phiIndex));
336 rdoList.push_back(hit_id);
337 }
338
339 std::sort(rdoList.begin(), rdoList.end());
340 const int firstStrip = m_stripID->strip(rdoList.front());
341 const int lastStrip = m_stripID->strip(rdoList.back());
342
343 const InDetDD::SCT_ModuleSideDesign* design;
344 if (pDE->isBarrel()) {
345 design = (static_cast<const InDetDD::SCT_ModuleSideDesign*>(
346 &pDE->design()));
347 } else {
348 design = (static_cast<const InDetDD::StripStereoAnnulusDesign*>(
349 &pDE->design()));
350 }
351
352 const int row = m_stripID->row(rdoList.front());
353 const int firstStrip1D = design->strip1Dim(firstStrip, row);
354 const int lastStrip1D = design->strip1Dim(lastStrip, row);
355 const InDetDD::SiCellId cell1(firstStrip1D);
356 const InDetDD::SiCellId cell2(lastStrip1D);
357 const InDetDD::SiLocalPosition firstStripPos(
358 pDE->rawLocalPositionOfCell(cell1));
359 const InDetDD::SiLocalPosition lastStripPos(
360 pDE->rawLocalPositionOfCell(cell2));
361 const InDetDD::SiLocalPosition centre(
362 (firstStripPos + lastStripPos) * 0.5);
363 const std::pair<InDetDD::SiLocalPosition, InDetDD::SiLocalPosition>
364 ends(design->endsOfStrip(centre));
365 const double stripLength(
366 std::abs(ends.first.xEta() - ends.second.xEta()));
367 const double width =
368 design->stripPitch() * (lastStrip - firstStrip + 1);
369
370 double const phiWidth = static_cast<double>((phiIndicesMax - phiIndicesMin) + 1);
371 InDet::SiWidth siWidth(Amg::Vector2D(phiWidth, 1),
372 Amg::Vector2D(width, stripLength));
373
374 xaod_scl->setIdentifier(rdoList.front().get_compact());
375 xaod_scl->setRDOlist(std::move(rdoList));
376 xaod_scl->setChannelsInPhi(siWidth.colRow()[0]);
377
378 }
379 ++strip_idx;
380 }
381 }
382
383 ATH_MSG_DEBUG("Converted " << pixel_idx << " pixel clusters, " << strip_idx
384 << " strip clusters");
385
386 m_nMeas += traccc_measurements.size();
387 m_nPix += pixel_idx;
388 m_nStrip += strip_idx;
389
390 // ---- Write outputs ----
392 ctx};
393 ATH_CHECK(pixelHandle.record(std::move(pixel_cont), std::move(pixel_aux)));
394
396 ctx};
397 ATH_CHECK(stripHandle.record(std::move(strip_cont), std::move(strip_aux)));
398
399 return StatusCode::SUCCESS;
400}
401
403{
404 ATH_MSG_DEBUG("Finalizing.");
405
406 ATH_MSG_DEBUG("Received total number of measurements = " << m_nMeas
407 << ", of which pixel clusters = " << m_nPix
408 << " and strip clusters = " << m_nStrip);
409
410 ATH_MSG_DEBUG("Successfully finalized");
411 return StatusCode::SUCCESS;
412}
413
414} // namespace ActsTrk
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
const double width
SG::ReadHandleKey< traccc::edm::measurement_collection::buffer > m_inputMeasKey
SG::WriteHandleKey< xAOD::StripClusterContainer > m_outputStripKey
virtual StatusCode finalize() override
Function finalizing the algorthm.
SG::ReadHandleKey< traccc::edm::silicon_cell_collection::buffer > m_inputCellsKey
SG::ReadHandleKey< traccc::edm::silicon_cluster_collection::buffer > m_inputClusterKey
ServiceHandle< ActsTrk::IDeviceDetectorDescriptionProviderSvc > m_detDescSvc
ToolHandle< AthDevice::IMemoryResourceTool > m_hostMR
std::atomic< int > m_nPix
The object counters for debug prints in finalize method {.
const PixelID * m_pixelID
Conversion helpers (to retrieve module design, hash, etc.) {.
const std::unordered_map< uint64_t, Identifier > * m_detrayToAthena
The athena <-> detray identifier map.
SG::WriteHandleKey< xAOD::PixelClusterContainer > m_outputPixelKey
virtual StatusCode initialize() override
Function initializing the algorithm.
const InDetDD::SCT_DetectorManager * m_stripManager
const InDetDD::PixelDetectorManager * m_pixelManager
virtual StatusCode execute(const EventContext &ctx) const override
Function executing the algorithm.
const ServiceHandle< StoreGateSvc > & detStore() const
a typed memory pool that saves time spent allocation small object.
Definition DataPool.h:63
Derived DataVector<T>.
Definition DataVector.h:795
This is a "hash" representation of an Identifier.
value_type get_compact() const
Get the compact id.
Dedicated detector manager extending the functionality of the SiDetectorManager with dedicated pixel ...
virtual const SiDetectorElement * getDetectorElement(const Identifier &id) const override
access to individual elements : via Identifier
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.
Dedicated detector manager extending the functionality of the SiDetectorManager with dedicated SCT in...
virtual const SiDetectorElement * getDetectorElement(const Identifier &id) const override
access to individual elements via Identifier
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 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):
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
HepGeom::Point3D< double > globalPosition(const HepGeom::Point3D< double > &localPos) const
transform a reconstruction local position into a global position (inline):
Amg::Vector2D rawLocalPositionOfCell(const SiCellId &cellId) const
Returns position (center) of cell.
const Amg::Vector2D & widthPhiRZ() const
Definition SiWidth.h:121
const Amg::Vector2D & colRow() const
Definition SiWidth.h:115
This is an Identifier helper class for the Pixel subdetector.
Definition PixelID.h:69
IdentifierHash wafer_hash(Identifier wafer_id) const
wafer hash from id
Definition PixelID.h:378
This is an Identifier helper class for the SCT subdetector.
Definition SCT_ID.h:68
IdentifierHash wafer_hash(const Identifier &wafer_id) const
wafer hash from id - optimized
Definition SCT_ID.h:487
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
void setChannelsInPhiEta(int channelsInPhi, int channelsInEta)
Sets the dimensions of the cluster in numbers of channels in phi (x) and eta (y) directions.
ConstVectorMap< 3 > globalPosition() const
Returns the global position of the pixel cluster.
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.
void setRDOlist(const std::vector< Identifier > &rdolist)
Sets 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.
void setIdentifierHash(const DetectorIDHashType idHash)
Sets the IdentifierHash of the measurement (corresponds to the detector element IdentifierHash).
void setIdentifier(const DetectorIdentType measId)
Sets the full Identifier of the measurement.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
void fillPixelCluster(const MEAS &meas, const Identifier &athenaId, const PixelID *pixelID, const InDetDD::PixelDetectorManager *pixelManager, xAOD::PixelCluster &xaod_pcl, std::size_t combinedIndex)
void fillStripCluster(const MEAS &meas, const Identifier &athenaId, const SCT_ID *stripID, const InDetDD::SCT_DetectorManager *stripManager, xAOD::StripCluster &xaod_scl, std::size_t combinedIndex)
std::pair< std::unique_ptr< ContainerT >, std::unique_ptr< AuxContainerT > > makeOutputContainer(const EventContext &ctx, int n)
std::pair< int, int > countPixelStrip(const traccc::edm::measurement_collection::const_device &measurements)
Count the number of measurements 2D (pixel) vs 1D (strip).
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
@ ALWAYS_TRACK_INDICES
Always track indices, regardless of the setting of the ownership policy.
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Framework include files.
Definition libname.h:15
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
StripCluster_v1 StripCluster
Define the version of the strip cluster class.
PixelCluster_v1 PixelCluster
Define the version of the pixel cluster class.