ATLAS Offline Software
Loading...
Searching...
No Matches
xAODClusterMaker.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4
12
13constexpr bool enableBenchmark =
14#ifdef STANDALONE_FPGA_BENCHMARK
15true;
16#else
17false;
18#endif
19
21
23#include "AthenaKernel/Chrono.h"
25#include "CxxUtils/span.h"
26#include "Identifier/Identifier.h"
31#include <bit>
32
33
34namespace {
35
36uint64_t to64 (const uint32_t* x)
37{
38 struct { uint32_t a[2]; } s = {x[0], x[1]};
39 return std::bit_cast<uint64_t> (s);
40}
41
42} // anonymous namespace
43
44
46 ATH_MSG_INFO("Initialising xAODClusterMaker tool");
47
48 // Initialise the write handles
49 ATH_CHECK(m_pixelClustersKey.initialize());
50 ATH_CHECK(m_stripClustersKey.initialize());
51
52 // Initialise the chrono service
53 ATH_CHECK(m_chronoSvc.retrieve());
54
55 return StatusCode::SUCCESS;
56}
57
59 const uint32_t* stripClusters,
60 const EFTrackingTransient::Metadata *metadata,
61 const EventContext &ctx) const {
62 ATH_MSG_DEBUG("Making xAOD::StripClusterContainer");
63
65
66 if (!m_doBulkCopy) {
67 ATH_CHECK(stripClustersHandle.record(std::make_unique<xAOD::StripClusterContainer>(), std::make_unique<xAOD::StripClusterAuxContainer>()));
68
69
70 for (unsigned int i = 0; i < metadata->numOfStripClusters; i++)
71 {
72 // Push back numClusters of StripCluster
73 auto stripCl = stripClustersHandle->push_back(std::make_unique<xAOD::StripCluster>());
74
75 // Build Matrix
76 Eigen::Matrix<float, 1, 1> localPosition;
77 Eigen::Matrix<float, 1, 1> localCovariance;
78 int row = 0; // idhash
79 unsigned int idHash = stripClusters[row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i + 16];
80 row = 1; // id
81 uint64_t id = to64 (stripClusters + row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i*2 + 16);
82
83 std::vector<Identifier> RDOs;
84 row = 3; // rdo w1
85 unsigned long long rdo = to64 (stripClusters + row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i*2 + 16);
86 if (rdo) RDOs.push_back(Identifier(rdo));
87
88 row = 5; // rdo w2
89 rdo = to64 (stripClusters + row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i*2 + 16);
90 if (rdo) RDOs.push_back(Identifier(rdo));
91
92 row = 7; // local x
93 localPosition(0, 0) = std::bit_cast<float>(stripClusters[row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i + 16]);
94 row = 8; // local covariance xx
95 localCovariance(0, 0) = std::bit_cast<float>(stripClusters[row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i + 16]);
96 row = 9; // global x
97 float globalX = std::bit_cast<float>(stripClusters[row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i + 16]);
98 row = 10; // global y
99 float globalY = std::bit_cast<float>(stripClusters[row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i + 16]);
100 row = 11; // global z
101 float globalZ = std::bit_cast<float>(stripClusters[row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i + 16]);
102 row = 12; // channels in phi
103 auto channelsinPhi = stripClusters[row * EFTrackingTransient::MAX_STRIP_CLUSTERS + i + 16];
104
105
106 Eigen::Matrix<float, 3, 1> globalPosition(globalX, globalY, globalZ);
107 stripCl->setMeasurement<1>(idHash, localPosition, localCovariance);
108
109 stripCl->setIdentifier(id);
110 stripCl->setRDOlist(RDOs);
111 stripCl->globalPosition() = globalPosition;
112 stripCl->setChannelsInPhi(channelsinPhi);
113 }
114
115 return StatusCode::SUCCESS;
116 }
117
118 ATH_MSG_DEBUG("Doing Strip bulk copy (optimized)");
119 // --------------------------
120 // Create the container and aux. container
121 // --------------------------
122 const size_t nClusters = metadata->numOfStripClusters;
123 DataPool<xAOD::StripCluster> stripPool{ctx};
124 stripPool.reserve(nClusters);
125 auto stripCl = std::make_unique<xAOD::StripClusterContainer>(SG::VIEW_ELEMENTS, SG::ALWAYS_TRACK_INDICES);
126 {
127 if constexpr (enableBenchmark) Athena::Chrono chrono("Strip object creating", m_chronoSvc.get());
128 stripCl->push_new(nClusters, [&stripPool]() { return stripPool.nextElementPtr(); });
129 }
130 auto stripClAux = std::make_unique<xAOD::StripClusterAuxContainer>();
131 stripClAux->resize(nClusters);
132 stripCl->setStore(stripClAux.get());
133 // --------------------------
134 // Access fixed-size attributes directly (rows/offsets consistent with !m_doBulkCopy)
135 // --------------------------
137 const size_t offset = 16;
138
139 // Treat the raw column-major buffer as 32-bit words; 64-bit values span two words.
140 const uint32_t* base = stripClusters;
141
142 auto load_u64 = [&](size_t row, size_t idx) -> uint64_t {
143 const uint32_t* p32 = base + row * N + offset + 2 * idx;
144 return *reinterpret_cast<const uint64_t*>(p32);
145 };
146 auto load_f32 = [&](size_t row, size_t idx) -> float {
147 return std::bit_cast<float>(*(base + row * N + offset + idx));
148 };
149 auto load_u32 = [&](size_t row, size_t idx) -> uint32_t {
150 return *(base + row * N + offset + idx);
151 };
152
153 // Column rows (as in !m_doBulkCopy)
154 constexpr size_t ROW_idHash = 0;
155 constexpr size_t ROW_identifier = 1; // 64-bit (two u32 words)
156 // (row 2 unused for Strip; keep aligned with transient layout)
157 constexpr size_t ROW_rdo_w1 = 3; // 64-bit (two u32 words)
158 constexpr size_t ROW_rdo_w2 = 5; // 64-bit (two u32 words)
159 constexpr size_t ROW_localPosX = 7; // float (from u32)
160 constexpr size_t ROW_localCovXX = 8; // float (from u32)
161 constexpr size_t ROW_gpX = 9; // float (from u32)
162 constexpr size_t ROW_gpY = 10; // float (from u32)
163 constexpr size_t ROW_gpZ = 11; // float (from u32)
164 constexpr size_t ROW_channelsPhi = 12; // int (from u32)
165
166 // --------------------------
167 // Precompute spans into aux data store (types match the non-bulk path)
168 // --------------------------
169 if (nClusters > 0) {
170 static const SG::Accessor<unsigned int> idHashAcc("identifierHash");
171 static const SG::Accessor<unsigned long> idAcc("identifier");
172 static const SG::Accessor<std::array<float, 1>> locPosXAcc("localPositionDim1");
173 static const SG::Accessor<std::array<float, 1>> locCovXXAcc("localCovarianceDim1");
174 static const SG::Accessor<std::array<float, 3>> gpAcc("globalPosition");
175 static const SG::Accessor<int> channelsPhiAcc("channelsInPhi");
177
178 auto idHashSpan = idHashAcc.getDataSpan(*stripCl);
179 auto idSpan = idAcc.getDataSpan(*stripCl);
180 auto locPosXSpan = locPosXAcc.getDataSpan(*stripCl);
181 auto locCovXXSpan = locCovXXAcc.getDataSpan(*stripCl);
182 auto gpSpan = gpAcc.getDataSpan(*stripCl);
183 auto channelsPhiSpan = channelsPhiAcc.getDataSpan(*stripCl);
184 auto rdoSpan = rdoListAcc.getDataSpan(*stripCl);
185
186 // --------------------------
187 // Vectorized bulk assignments
188 // --------------------------
189 {
190 if constexpr (enableBenchmark) Athena::Chrono chrono("Strip assignments", m_chronoSvc.get());
191 for (size_t i = 0; i < nClusters; ++i) {
192 // idHash: 32-bit value
193 idHashSpan[i] = static_cast<unsigned int>(load_u32(ROW_idHash, i));
194
195 // identifier: 64-bit (two words)
196 idSpan[i] = static_cast<unsigned long long>(load_u64(ROW_identifier, i));
197
198 // local position / covariance (Dim1)
199 locPosXSpan[i][0] = load_f32(ROW_localPosX, i);
200 locCovXXSpan[i][0] = load_f32(ROW_localCovXX, i);
201
202 // global position (x,y,z)
203 gpSpan[i][0] = load_f32(ROW_gpX, i);
204 gpSpan[i][1] = load_f32(ROW_gpY, i);
205 gpSpan[i][2] = load_f32(ROW_gpZ, i);
206
207 // channels in phi
208 channelsPhiSpan[i] = static_cast<int>(load_u32(ROW_channelsPhi, i));
209
210 // RDO list: up to 2 entries (Identifier)
211 auto& rdoList = rdoSpan[i];
212 rdoList.reserve(2);
213 uint64_t rdo1 = load_u64(ROW_rdo_w1, i);
214 uint64_t rdo2 = load_u64(ROW_rdo_w2, i);
215 if (rdo1) rdoList.emplace_back(rdo1);
216 if (rdo2) rdoList.emplace_back(rdo2);
217 }
218 }
219 }
220
221 {
222 if constexpr (enableBenchmark) Athena::Chrono chrono("Strip Copy", m_chronoSvc.get());
223 ATH_CHECK(stripClustersHandle.record(std::move(stripCl), std::move(stripClAux)));
224 }
225
226 return StatusCode::SUCCESS;
227}
228
229
230
233 const EFTrackingTransient::Metadata *metadata,
234 const EventContext &ctx) const {
235 ATH_MSG_DEBUG("Making xAOD::StripClusterContainer");
236
238 m_stripClustersKey , ctx};
239
240 ATH_CHECK(stripClustersHandle.record(
241 std::make_unique<xAOD::StripClusterContainer>(),
242 std::make_unique<xAOD::StripClusterAuxContainer>()));
243
244 int rdoIndexCounter = 0;
245
246 for (unsigned int i = 0; i < metadata->numOfStripClusters; i++) {
247 // Push back numClusters of StripCluster
248 auto stripCl =
249 stripClustersHandle->push_back(std::make_unique<xAOD::StripCluster>());
250
251 // Build Matrix
252 Eigen::Matrix<float, 1, 1> localPosition;
253 Eigen::Matrix<float, 1, 1> localCovariance;
254
255 localPosition(0, 0) = scAux.localPosition.at(i);
256 localCovariance(0, 0) = scAux.localCovariance.at(i);
257
258 Eigen::Matrix<float, 3, 1> globalPosition(
259 scAux.globalPosition.at(i * 3), scAux.globalPosition.at(i * 3 + 1),
260 scAux.globalPosition.at(i * 3 + 2));
261
262 std::vector<Identifier> RDOs;
263 RDOs.reserve(metadata->scRdoIndex[i]);
264 // Cover RDO
265 for (unsigned int j = 0; j < metadata->scRdoIndex[i]; ++j) {
266 RDOs.push_back(Identifier(scAux.rdoList.at(rdoIndexCounter + j)));
267 }
268
269 rdoIndexCounter += metadata->scRdoIndex[i];
270
271 stripCl->setMeasurement<1>(scAux.idHash.at(i), localPosition,
272 localCovariance);
273 stripCl->setIdentifier(scAux.id.at(i));
274 stripCl->setRDOlist(RDOs);
275 stripCl->globalPosition() = globalPosition;
276 stripCl->setChannelsInPhi(scAux.channelsInPhi.at(i));
277 }
278 return StatusCode::SUCCESS;
279}
280
281
283 const uint32_t* pixelClusters,
284 const EFTrackingTransient::Metadata *metadata,
285 const EventContext &ctx) const {
286 ATH_MSG_DEBUG("Making xAOD::PixelClusterContainer");
287
288
290
291 if (!m_doBulkCopy) {
292 // --------------------------------------------------------------------
293 // proceed with the element-wise method
294 // --------------------------------------------------------------------
295 ATH_CHECK(pixelClustersHandle.record(std::make_unique<xAOD::PixelClusterContainer>(),std::make_unique<xAOD::PixelClusterAuxContainer>()));
296
297 ATH_CHECK(pixelClustersHandle.isValid());
298
299 for (unsigned int i = 0; i < metadata->numOfPixelClusters; i++)
300 {
301 // Push back numClusters of StripCluster
302 auto pixelCl = pixelClustersHandle->push_back(std::make_unique<xAOD::PixelCluster>());
303
304 int row = 0; // idhash
305 unsigned int idHash = pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16];
306 row = 1; // id
307 unsigned long long id = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
308
309 std::vector<Identifier> RDOs;
310 row = 3; // rdo w1
311 unsigned long long rdo = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
312 if (rdo) RDOs.push_back(Identifier(rdo));
313
314 row = 5; // rdo w2
315 rdo = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
316 if (rdo) RDOs.push_back(Identifier(rdo));
317
318 row = 7; // rdo w3
319 rdo = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
320 if (rdo) RDOs.push_back(Identifier(rdo));
321
322 row = 9; // rdo w4
323 rdo = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
324 if (rdo) RDOs.push_back(Identifier(rdo));
325
326 Eigen::Matrix<float, 2, 1> localPosition;
327 Eigen::Matrix<float, 2, 2> localCovariance;
328 localCovariance.setZero();
329 row = 11; // local x
330 localPosition(0 , 0) = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
331
332 row = 12; // local y
333 localPosition(1 , 1) = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
334
335 row = 13; // local covariance xx
336 localCovariance(0, 0) = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
337
338 row = 14; // local covariance yy
339 localCovariance(1, 1) = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
340
341 row = 15; // global x
342 float globalX = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
343
344 row = 16; // global y
345 float globalY = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
346
347 row = 17; // global
348 float globalZ = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
349
350 row = 18; // channels in phi
351 int channelsInPhi = pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16];
352
353 row = 19; // channels in eta
354 int channelsInEta = pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16];
355
356 row = 20; // width in eta
357 double widthInEta = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
358
359 row = 21; // total ToT
360 int totalToT = pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16];
361
362 Eigen::Matrix<float, 3, 1> globalPosition(globalX, globalY, globalZ);
363
364 pixelCl->setMeasurement<2>(idHash, localPosition,localCovariance);
365 pixelCl->setIdentifier(id);
366 pixelCl->setRDOlist(RDOs);
367 pixelCl->globalPosition() = globalPosition;
368 pixelCl->setTotalToT(totalToT);
369 pixelCl->setChannelsInPhiEta(channelsInPhi, channelsInEta);
370 pixelCl->setWidthInEta(widthInEta);
371 }
372 return StatusCode::SUCCESS;
373 }
374
375 ATH_MSG_DEBUG("Doing bulk copy (optimized)");
376 // --------------------------
377 // Create the container and aux. container
378 // --------------------------
379 const size_t nClusters = metadata->numOfPixelClusters;
380 DataPool<xAOD::PixelCluster> pixelPool{ctx};
381 pixelPool.reserve(nClusters);
382 auto pixelCl = std::make_unique<xAOD::PixelClusterContainer>(SG::VIEW_ELEMENTS, SG::ALWAYS_TRACK_INDICES);
383 {
384 if constexpr (enableBenchmark) Athena::Chrono chrono("Pixel object creating", m_chronoSvc.get());
385 pixelCl->push_new(nClusters, [&pixelPool]() { return pixelPool.nextElementPtr(); });
386 }
387 auto pixelClAux = std::make_unique<xAOD::PixelClusterAuxContainer>();
388 pixelClAux->resize(nClusters);
389 pixelCl->setStore(pixelClAux.get());
390
391 // --------------------------
392 // Access fixed-size attributes directly (rows/offsets as in !m_doBulkCopy)
393 // --------------------------
395 const size_t offset = 16;
396
397 // Treat the raw column-major buffer as 32-bit words; 64-bit values span two words.
398 const uint32_t* base = pixelClusters;
399
400 auto load_u64 = [&](size_t row, size_t idx) -> uint64_t {
401 const uint32_t* p32 = base + row * N + offset + 2 * idx;
402 return *reinterpret_cast<const uint64_t*>(p32);
403 };
404 auto load_f32 = [&](size_t row, size_t idx) -> float {
405 return std::bit_cast<float>(*(base + row * N + offset + idx));
406 };
407 auto load_u32 = [&](size_t row, size_t idx) -> uint32_t {
408 return *(base + row * N + offset + idx);
409 };
410
411 // Row layout (must match the element-wise path)
412 constexpr size_t ROW_idHash = 0;
413 constexpr size_t ROW_identifier = 1; // u64
414 constexpr size_t ROW_rdo_w1 = 3; // u64
415 constexpr size_t ROW_rdo_w2 = 5; // u64
416 constexpr size_t ROW_rdo_w3 = 7; // u64
417 constexpr size_t ROW_rdo_w4 = 9; // u64
418 constexpr size_t ROW_localX = 11; // f32
419 constexpr size_t ROW_localY = 12; // f32
420 constexpr size_t ROW_covXX = 13; // f32
421 constexpr size_t ROW_covYY = 14; // f32
422 constexpr size_t ROW_gpX = 15; // f32
423 constexpr size_t ROW_gpY = 16; // f32
424 constexpr size_t ROW_gpZ = 17; // f32
425 constexpr size_t ROW_channelsPhi = 18; // i32
426 constexpr size_t ROW_channelsEta = 19; // i32
427 constexpr size_t ROW_widthEta = 20; // f32
428 constexpr size_t ROW_totalToT = 21; // i32
429
430 // --------------------------
431 // Precompute spans into aux data store (types aligned with !m_doBulkCopy behavior)
432 // --------------------------
433 if (nClusters > 0) {
434 static const SG::Accessor<unsigned int> idHashAcc("identifierHash");
435 static const SG::Accessor<unsigned long> idAcc("identifier");
436 static const SG::Accessor<std::array<float, 3>> gpAcc("globalPosition");
437 static const SG::Accessor<std::array<float, 2>> locPosAcc("localPositionDim2");
438 static const SG::Accessor<std::array<float, 4>> locCovAcc("localCovarianceDim2");
439 static const SG::Accessor<int> totalToTAcc("totalToT");
440 static const SG::Accessor<int> channelsPhiAcc("channelsInPhi");
441 static const SG::Accessor<int> channelsEtaAcc("channelsInEta");
442 static const SG::Accessor<float> widthEtaAcc("widthInEta");
444
445
446 auto idHashSpan = idHashAcc.getDataSpan(*pixelCl);
447 auto idSpan = idAcc.getDataSpan(*pixelCl);
448 auto gpSpan = gpAcc.getDataSpan(*pixelCl);
449 auto locPosSpan = locPosAcc.getDataSpan(*pixelCl);
450 auto locCovSpan = locCovAcc.getDataSpan(*pixelCl);
451 auto totalToTSpan = totalToTAcc.getDataSpan(*pixelCl);
452 auto channelsPhiSpan = channelsPhiAcc.getDataSpan(*pixelCl);
453 auto channelsEtaSpan = channelsEtaAcc.getDataSpan(*pixelCl);
454 auto widthEtaSpan = widthEtaAcc.getDataSpan(*pixelCl);
455 auto rdoSpan = rdoListAcc.getDataSpan(*pixelCl);
456
457 // --------------------------
458 // Vectorized bulk assignments
459 // --------------------------
460 {
461 if constexpr (enableBenchmark) Athena::Chrono chrono("Pixel assignments", m_chronoSvc.get());
462 for (size_t i = 0; i < nClusters; ++i) {
463 // Basic ids
464 idHashSpan[i] = static_cast<unsigned int>(load_u32(ROW_idHash, i));
465 idSpan[i] = static_cast<unsigned long long>(load_u64(ROW_identifier, i));
466
467 // Local position (2x1)
468 locPosSpan[i][0] = load_f32(ROW_localX, i);
469 locPosSpan[i][1] = load_f32(ROW_localY, i);
470
471 // Local covariance (2x2) flattened as [xx, xy, yx, yy]
472 locCovSpan[i][0] = load_f32(ROW_covXX, i);
473 locCovSpan[i][3] = load_f32(ROW_covYY, i);
474
475 // Global position
476 gpSpan[i][0] = load_f32(ROW_gpX, i);
477 gpSpan[i][1] = load_f32(ROW_gpY, i);
478 gpSpan[i][2] = load_f32(ROW_gpZ, i);
479
480 // Discrete/int attrs
481 channelsPhiSpan[i] = static_cast<int>(load_u32(ROW_channelsPhi, i));
482 channelsEtaSpan[i] = static_cast<int>(load_u32(ROW_channelsEta, i));
483 widthEtaSpan[i] = load_f32(ROW_widthEta, i);
484 totalToTSpan[i] = static_cast<int>(load_u32(ROW_totalToT, i));
485
486 // RDOs (up to 4)
487 auto& rdoList = rdoSpan[i];
488 rdoList.reserve(4);
489 uint64_t r1 = load_u64(ROW_rdo_w1, i);
490 uint64_t r2 = load_u64(ROW_rdo_w2, i);
491 uint64_t r3 = load_u64(ROW_rdo_w3, i);
492 uint64_t r4 = load_u64(ROW_rdo_w4, i);
493 if (r1) rdoList.emplace_back(r1);
494 if (r2) rdoList.emplace_back(r2);
495 if (r3) rdoList.emplace_back(r3);
496 if (r4) rdoList.emplace_back(r4);
497 }
498 }
499 }
500
501 {
502 if constexpr (enableBenchmark) Athena::Chrono chrono("Pixel Copy", m_chronoSvc.get());
503 ATH_CHECK(pixelClustersHandle.record(std::move(pixelCl), std::move(pixelClAux)));
504 }
505
506 return StatusCode::SUCCESS;
507
508
509
510 return StatusCode::SUCCESS;
511}
512
513
514
517 const EFTrackingTransient::Metadata *metadata,
518 const EventContext &ctx) const {
519 ATH_MSG_DEBUG("Making xAOD::PixelClusterContainer");
520
521
523
524 if (!m_doBulkCopy) {
525 // --------------------------------------------------------------------
526 // proceed with the element-wise method
527 // --------------------------------------------------------------------
528 ATH_MSG_DEBUG("You are running the element-wise container creation method.");
529 if constexpr (enableBenchmark) Athena::Chrono chrono("ElementWiseMethod", m_chronoSvc.get());
530
531 ATH_CHECK(pixelClustersHandle.record(
532 std::make_unique<xAOD::PixelClusterContainer>(),
533 std::make_unique<xAOD::PixelClusterAuxContainer>()));
534
535 ATH_CHECK(pixelClustersHandle.isValid());
536 ATH_MSG_DEBUG("Container '" << m_pixelClustersKey << "' initialised");
537
538 int rdoIndexCounter = 0;
539
540 for (unsigned int i = 0; i < metadata->numOfPixelClusters; i++) {
541 // Push back numClusters of PixelCluster
542 auto pixelCl = pixelClustersHandle->push_back(
543 std::make_unique<xAOD::PixelCluster>());
544
545 Eigen::Matrix<float, 2, 1> localPosition(
546 pxAux.localPosition[i * 2], pxAux.localPosition[i * 2 + 1]);
547 Eigen::Matrix<float, 2, 2> localCovariance;
548 localCovariance.setZero();
549 localCovariance(0, 0) = pxAux.localCovariance[i * 2];
550 localCovariance(1, 1) = pxAux.localCovariance[i * 2 + 1];
551 Eigen::Matrix<float, 3, 1> globalPosition(
552 pxAux.globalPosition[i * 3], pxAux.globalPosition[i * 3 + 1],
553 pxAux.globalPosition[i * 3 + 2]);
554
555 std::vector<Identifier> RDOs;
556 RDOs.reserve(metadata->pcRdoIndex[i]);
557 // Cover RDO
558 for (unsigned int j = 0; j < metadata->pcRdoIndex[i]; ++j) {
559 RDOs.push_back(Identifier(pxAux.rdoList[rdoIndexCounter + j]));
560 }
561
562 rdoIndexCounter += metadata->pcRdoIndex[i];
563
564 pixelCl->setMeasurement<2>(pxAux.idHash[i], localPosition,
565 localCovariance);
566 pixelCl->setIdentifier(pxAux.id[i]);
567 pixelCl->setRDOlist(RDOs);
568 pixelCl->globalPosition() = globalPosition;
569 pixelCl->setTotalToT(pxAux.totalToT[i]);
570 pixelCl->setChannelsInPhiEta(pxAux.channelsInPhi[i],
571 pxAux.channelsInEta[i]);
572 pixelCl->setWidthInEta(pxAux.widthInEta[i]);
573 }
574
575 return StatusCode::SUCCESS;
576 }
577
578 // --------------------------------------------------------------------
579 // proceed with the bulk copy method
580 // --------------------------------------------------------------------
581
582 ATH_MSG_DEBUG("You are running the bulk copy container creation method.");
583 if constexpr (enableBenchmark) Athena::Chrono chrono("BulkCopyMethod", m_chronoSvc.get());
584
585 // --------------------------
586 // Create the container and aux. container
587 // --------------------------
588 auto pixelCl = std::make_unique<xAOD::PixelClusterContainer>();
589 auto pixelClAux = std::make_unique<xAOD::PixelClusterAuxContainer>();
590 pixelCl->setStore(pixelClAux.get());
591
592 // Pre-allocate memory for all clusters in the AuxContainer
593 // and reserve the same space in the container.
594 const size_t nClusters = metadata->numOfPixelClusters;
595 pixelClAux->resize(nClusters);
596 pixelCl->reserve(nClusters);
597
598 // Now, push back the PixelCluster objects
599 // and create them all at once.
600 // Note, that no data is set yet,
601 // we will do that in the next step.
602 for (size_t i = 0; i < nClusters; ++i) {
603 pixelCl->push_back(std::make_unique<xAOD::PixelCluster>());
604 }
605
606 // --------------------------
607 // Prepare local buffers for each of the
608 // fixed-size attributes.
609 // --------------------------
610
611 std::vector<long unsigned int> identifierBuffer(nClusters);
612 std::vector<unsigned int> idHashBuffer(nClusters);
613 std::vector<std::array<float, 3>> gpBuffer(nClusters);
614 std::vector<float> localPosX(nClusters);
615 std::vector<float> localPosY(nClusters);
616 std::vector<float> localCovXX(nClusters);
617 std::vector<float> localCovYY(nClusters);
618 std::vector<int> totalToTBuffer(nClusters);
619 std::vector<float> widthInEtaBuffer(nClusters);
620 std::vector<int> channelsInPhiBuffer(nClusters);
621 std::vector<int> channelsInEtaBuffer(nClusters);
622
623 for (size_t i = 0; i < nClusters; ++i) {
624
625 // Fill the identifierBuffer
626 identifierBuffer[i] = pxAux.id[i];
627
628 // Fill the idHashBuffer
629 idHashBuffer[i] = pxAux.idHash[i];
630
631 // Fill the globalPositionBuffers
632 gpBuffer[i] = {
633 pxAux.globalPosition[3 * i],
634 pxAux.globalPosition[3 * i + 1],
635 pxAux.globalPosition[3 * i + 2],
636 };
637
638 // Fill the localPositionBuffers
639 localPosX[i] = pxAux.localPosition[2 * i];
640 localPosY[i] = pxAux.localPosition[2 * i + 1];
641
642 // Fill the localCovBuffer[i]
643 localCovXX[i] = pxAux.localCovariance[2 * i];
644 localCovYY[i] = pxAux.localCovariance[2 * i + 1];
645
646 // Fill the totalToTBuffer
647 totalToTBuffer[i] = pxAux.totalToT[i];
648
649 // Fill the widthInEtaBuffer
650 widthInEtaBuffer[i] = pxAux.widthInEta[i];
651
652 // Fill the channelsInPhiEtaBuffer
653 channelsInPhiBuffer[i] = pxAux.channelsInPhi[i];
654 channelsInEtaBuffer[i] = pxAux.channelsInEta[i];
655 }
656
657 // --------------------------
658 // Now, use SG::Accessors to do a bulk copy into
659 // the container memory.
660 // --------------------------
661
662 // FIXED-SIZE ATTRIBUTES
663 static const SG::Accessor<long unsigned int> idAcc("identifier");
664 static const SG::Accessor<unsigned int> idHashAcc("idHash");
665 static const SG::Accessor<float> localPosXAcc("localPositionX");
666 static const SG::Accessor<float> localPosYAcc("localPositionY");
667 static const SG::Accessor<float> localCovXXAcc("localCovarianceXX");
668 static const SG::Accessor<float> localCovYYAcc("localCovarianceYY");
669 static const SG::Accessor<int> totAcc("totalToT");
670 static const SG::Accessor<float> widthEtaAcc("widthInEta");
671 static const SG::Accessor<int> channelsInPhiAcc("channelsInPhi");
672 static const SG::Accessor<int> channelsInEtaAcc("channelsInEta");
673
674 // VARIABLE-LENGTH ATTRIBUTES
676 "globalPosition");
677
678 // Get spans into the container
679 auto idSpan = idAcc.getDataSpan(*pixelCl);
680 auto idHashSpan = idHashAcc.getDataSpan(*pixelCl);
681 auto locPosXSpan = localPosXAcc.getDataSpan(*pixelCl);
682 auto locPosYSpan = localPosYAcc.getDataSpan(*pixelCl);
683 auto locCovXXSpan = localCovXXAcc.getDataSpan(*pixelCl);
684 auto locCovYYSpan = localCovYYAcc.getDataSpan(*pixelCl);
685 auto totSpan = totAcc.getDataSpan(*pixelCl);
686 auto wEtaSpan = widthEtaAcc.getDataSpan(*pixelCl);
687 auto gpSpan = globalPosAcc.getDataSpan(*pixelCl);
688 auto channelsInPhiSpan = channelsInPhiAcc.getDataSpan(*pixelCl);
689 auto channelsInEtaSpan = channelsInEtaAcc.getDataSpan(*pixelCl);
690
691 // Bulk copy the fixed-size attributes
692 CxxUtils::copy_bounded(identifierBuffer, idSpan);
693 CxxUtils::copy_bounded(idHashBuffer, idHashSpan);
694 CxxUtils::copy_bounded(localPosX, locPosXSpan);
695 CxxUtils::copy_bounded(localPosY, locPosYSpan);
696 CxxUtils::copy_bounded(localCovXX, locCovXXSpan);
697 CxxUtils::copy_bounded(localCovYY, locCovYYSpan);
698 CxxUtils::copy_bounded(totalToTBuffer, totSpan);
699 CxxUtils::copy_bounded(widthInEtaBuffer, wEtaSpan);
700 CxxUtils::copy_bounded(gpBuffer, gpSpan);
701 CxxUtils::copy_bounded(channelsInPhiBuffer, channelsInPhiSpan);
702 CxxUtils::copy_bounded(channelsInEtaBuffer, channelsInEtaSpan);
703
704 // --------------------------
705 // Copy the variable-length data.
706 // We need to loop over the number of
707 // clusters to get access to each
708 // element.
709 // --------------------------
711 "rdoList");
712 auto rdoSpan = rdoListAcc.getDataSpan(*pixelCl);
713
714 int rdoIndexCounter = 0;
715 // loop over the clusters
716 for (size_t i = 0; i < nClusters; ++i) {
717 size_t nRDOs = metadata->pcRdoIndex[i];
718
719 // direct ref to destination vector
720 std::vector<unsigned long long> &rdosForThisCluster = rdoSpan[i];
721
722 // pre-size the vector
723 rdosForThisCluster.resize(nRDOs);
724
725 // direct element access
726 for (size_t j = 0; j < nRDOs; ++j) {
727 rdosForThisCluster[j] = pxAux.rdoList[rdoIndexCounter + j];
728 }
729 rdoIndexCounter += nRDOs;
730 }
731 // --------------------------
732 // Record the container + aux container into StoreGate,
733 // but now we do it AFTER filling the container!
734 // --------------------------
735
736 ATH_CHECK(pixelClustersHandle.record(std::move(pixelCl), std::move(pixelClAux)));
737
738 ATH_MSG_DEBUG("Bulk copy for fixed-size variables done.");
739 return StatusCode::SUCCESS;
740}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
Exception-safe IChronoSvc caller.
Helper class to provide type-safe access to aux data.
static const SG::AuxElement::Accessor< std::vector< Identifier::value_type > > rdoListAcc("rdoList")
static Double_t a
static const SG::AuxElement::Accessor< std::array< float, 3 > > globalPosAcc("globalPosition")
Handle class for recording to StoreGate.
#define x
Exception-safe IChronoSvc caller.
Definition Chrono.h:50
a typed memory pool that saves time spent allocation small object.
Definition DataPool.h:63
void reserve(unsigned int size)
Set the desired capacity.
pointer nextElementPtr()
obtain the next available element in pool by pointer pool is resized if its limit has been reached On...
Helper class to provide type-safe access to aux data.
span getDataSpan(AuxVectorData &container) const
Get a span over the auxilary data array.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
StatusCode makeStripClusterContainer(const EFTrackingTransient::StripClusterAuxInput &scAux, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
Make the strip cluster container.
StatusCode initialize() override
Initialise the tool.
SG::WriteHandleKey< xAOD::StripClusterContainer > m_stripClustersKey
Key for the strip clusters container to be created.
StatusCode makePixelClusterContainer(const EFTrackingTransient::PixelClusterAuxInput &pxAux, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
Make the pixel cluster container.
SG::WriteHandleKey< xAOD::PixelClusterContainer > m_pixelClustersKey
Key for the pixel clusters container to be created.
ServiceHandle< IChronoStatSvc > m_chronoSvc
Gaudi::Property< bool > m_doBulkCopy
Do bulk copy method.
Copy a range with bounds restriction.
std::string base
Definition hcg.cxx:81
OutputIterator copy_bounded(InputIterator begi, InputIterator endi, OutputIterator bego, OutputIterator endo)
Copy a range with bounds restriction.
constexpr uint32_t MAX_PIXEL_CLUSTERS
constexpr uint32_t MAX_STRIP_CLUSTERS
@ 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
Simplified version of the C++20 std::span.
The structure of the Metadata containing data after clusterization.
The PixelClusterAuxInput struct is used to simplify the creaction of the xAOD::PixelClusterContainer.
std::vector< unsigned long long > rdoList
The StripClusterAuxInput struct is used to simplify the creaction of the xAOD::StripClusterContainer.
std::vector< unsigned long long > rdoList
constexpr bool enableBenchmark