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 Eigen::Matrix<float, 3, 1> globalPosition(globalX, globalY, globalZ);
360
361 pixelCl->setMeasurement<2>(idHash, localPosition,localCovariance);
362 pixelCl->setIdentifier(id);
363 pixelCl->setRDOlist(RDOs);
364 pixelCl->globalPosition() = globalPosition;
365 pixelCl->setChannelsInPhiEta(channelsInPhi, channelsInEta);
366 pixelCl->setWidthInEta(widthInEta);
367 }
368 return StatusCode::SUCCESS;
369 }
370
371 ATH_MSG_DEBUG("Doing bulk copy (optimized)");
372 // --------------------------
373 // Create the container and aux. container
374 // --------------------------
375 const size_t nClusters = metadata->numOfPixelClusters;
376 DataPool<xAOD::PixelCluster> pixelPool{ctx};
377 pixelPool.reserve(nClusters);
378 auto pixelCl = std::make_unique<xAOD::PixelClusterContainer>(SG::VIEW_ELEMENTS, SG::ALWAYS_TRACK_INDICES);
379 {
380 if constexpr (enableBenchmark) Athena::Chrono chrono("Pixel object creating", m_chronoSvc.get());
381 pixelCl->push_new(nClusters, [&pixelPool]() { return pixelPool.nextElementPtr(); });
382 }
383 auto pixelClAux = std::make_unique<xAOD::PixelClusterAuxContainer>();
384 pixelClAux->resize(nClusters);
385 pixelCl->setStore(pixelClAux.get());
386
387 // --------------------------
388 // Access fixed-size attributes directly (rows/offsets as in !m_doBulkCopy)
389 // --------------------------
391 const size_t offset = 16;
392
393 // Treat the raw column-major buffer as 32-bit words; 64-bit values span two words.
394 const uint32_t* base = pixelClusters;
395
396 auto load_u64 = [&](size_t row, size_t idx) -> uint64_t {
397 const uint32_t* p32 = base + row * N + offset + 2 * idx;
398 return *reinterpret_cast<const uint64_t*>(p32);
399 };
400 auto load_f32 = [&](size_t row, size_t idx) -> float {
401 return std::bit_cast<float>(*(base + row * N + offset + idx));
402 };
403 auto load_u32 = [&](size_t row, size_t idx) -> uint32_t {
404 return *(base + row * N + offset + idx);
405 };
406
407 // Row layout (must match the element-wise path)
408 constexpr size_t ROW_idHash = 0;
409 constexpr size_t ROW_identifier = 1; // u64
410 constexpr size_t ROW_rdo_w1 = 3; // u64
411 constexpr size_t ROW_rdo_w2 = 5; // u64
412 constexpr size_t ROW_rdo_w3 = 7; // u64
413 constexpr size_t ROW_rdo_w4 = 9; // u64
414 constexpr size_t ROW_localX = 11; // f32
415 constexpr size_t ROW_localY = 12; // f32
416 constexpr size_t ROW_covXX = 13; // f32
417 constexpr size_t ROW_covYY = 14; // f32
418 constexpr size_t ROW_gpX = 15; // f32
419 constexpr size_t ROW_gpY = 16; // f32
420 constexpr size_t ROW_gpZ = 17; // f32
421 constexpr size_t ROW_channelsPhi = 18; // i32
422 constexpr size_t ROW_channelsEta = 19; // i32
423 constexpr size_t ROW_widthEta = 20; // f32
424 constexpr size_t ROW_totalToT = 21; // i32
425
426 // --------------------------
427 // Precompute spans into aux data store (types aligned with !m_doBulkCopy behavior)
428 // --------------------------
429 if (nClusters > 0) {
430 static const SG::Accessor<unsigned int> idHashAcc("identifierHash");
431 static const SG::Accessor<unsigned long> idAcc("identifier");
432 static const SG::Accessor<std::array<float, 3>> gpAcc("globalPosition");
433 static const SG::Accessor<std::array<float, 2>> locPosAcc("localPositionDim2");
434 static const SG::Accessor<std::array<float, 4>> locCovAcc("localCovarianceDim2");
435 static const SG::Accessor<int> totalToTAcc("totalToT");
436 static const SG::Accessor<int> channelsPhiAcc("channelsInPhi");
437 static const SG::Accessor<int> channelsEtaAcc("channelsInEta");
438 static const SG::Accessor<float> widthEtaAcc("widthInEta");
440
441
442 auto idHashSpan = idHashAcc.getDataSpan(*pixelCl);
443 auto idSpan = idAcc.getDataSpan(*pixelCl);
444 auto gpSpan = gpAcc.getDataSpan(*pixelCl);
445 auto locPosSpan = locPosAcc.getDataSpan(*pixelCl);
446 auto locCovSpan = locCovAcc.getDataSpan(*pixelCl);
447 auto totalToTSpan = totalToTAcc.getDataSpan(*pixelCl);
448 auto channelsPhiSpan = channelsPhiAcc.getDataSpan(*pixelCl);
449 auto channelsEtaSpan = channelsEtaAcc.getDataSpan(*pixelCl);
450 auto widthEtaSpan = widthEtaAcc.getDataSpan(*pixelCl);
451 auto rdoSpan = rdoListAcc.getDataSpan(*pixelCl);
452
453 // --------------------------
454 // Vectorized bulk assignments
455 // --------------------------
456 {
457 if constexpr (enableBenchmark) Athena::Chrono chrono("Pixel assignments", m_chronoSvc.get());
458 for (size_t i = 0; i < nClusters; ++i) {
459 // Basic ids
460 idHashSpan[i] = static_cast<unsigned int>(load_u32(ROW_idHash, i));
461 idSpan[i] = static_cast<unsigned long long>(load_u64(ROW_identifier, i));
462
463 // Local position (2x1)
464 locPosSpan[i][0] = load_f32(ROW_localX, i);
465 locPosSpan[i][1] = load_f32(ROW_localY, i);
466
467 // Local covariance (2x2) flattened as [xx, xy, yx, yy]
468 locCovSpan[i][0] = load_f32(ROW_covXX, i);
469 locCovSpan[i][3] = load_f32(ROW_covYY, i);
470
471 // Global position
472 gpSpan[i][0] = load_f32(ROW_gpX, i);
473 gpSpan[i][1] = load_f32(ROW_gpY, i);
474 gpSpan[i][2] = load_f32(ROW_gpZ, i);
475
476 // Discrete/int attrs
477 channelsPhiSpan[i] = static_cast<int>(load_u32(ROW_channelsPhi, i));
478 channelsEtaSpan[i] = static_cast<int>(load_u32(ROW_channelsEta, i));
479 widthEtaSpan[i] = load_f32(ROW_widthEta, i);
480 totalToTSpan[i] = static_cast<int>(load_u32(ROW_totalToT, i));
481
482 // RDOs (up to 4)
483 auto& rdoList = rdoSpan[i];
484 rdoList.reserve(4);
485 uint64_t r1 = load_u64(ROW_rdo_w1, i);
486 uint64_t r2 = load_u64(ROW_rdo_w2, i);
487 uint64_t r3 = load_u64(ROW_rdo_w3, i);
488 uint64_t r4 = load_u64(ROW_rdo_w4, i);
489 if (r1) rdoList.emplace_back(r1);
490 if (r2) rdoList.emplace_back(r2);
491 if (r3) rdoList.emplace_back(r3);
492 if (r4) rdoList.emplace_back(r4);
493 }
494 }
495 }
496
497 {
498 if constexpr (enableBenchmark) Athena::Chrono chrono("Pixel Copy", m_chronoSvc.get());
499 ATH_CHECK(pixelClustersHandle.record(std::move(pixelCl), std::move(pixelClAux)));
500 }
501
502 return StatusCode::SUCCESS;
503
504
505
506 return StatusCode::SUCCESS;
507}
508
509
510
513 const EFTrackingTransient::Metadata *metadata,
514 const EventContext &ctx) const {
515 ATH_MSG_DEBUG("Making xAOD::PixelClusterContainer");
516
517
519
520 if (!m_doBulkCopy) {
521 // --------------------------------------------------------------------
522 // proceed with the element-wise method
523 // --------------------------------------------------------------------
524 ATH_MSG_DEBUG("You are running the element-wise container creation method.");
525 if constexpr (enableBenchmark) Athena::Chrono chrono("ElementWiseMethod", m_chronoSvc.get());
526
527 ATH_CHECK(pixelClustersHandle.record(
528 std::make_unique<xAOD::PixelClusterContainer>(),
529 std::make_unique<xAOD::PixelClusterAuxContainer>()));
530
531 ATH_CHECK(pixelClustersHandle.isValid());
532 ATH_MSG_DEBUG("Container '" << m_pixelClustersKey << "' initialised");
533
534 int rdoIndexCounter = 0;
535
536 for (unsigned int i = 0; i < metadata->numOfPixelClusters; i++) {
537 // Push back numClusters of PixelCluster
538 auto pixelCl = pixelClustersHandle->push_back(
539 std::make_unique<xAOD::PixelCluster>());
540
541 Eigen::Matrix<float, 2, 1> localPosition(
542 pxAux.localPosition[i * 2], pxAux.localPosition[i * 2 + 1]);
543 Eigen::Matrix<float, 2, 2> localCovariance;
544 localCovariance.setZero();
545 localCovariance(0, 0) = pxAux.localCovariance[i * 2];
546 localCovariance(1, 1) = pxAux.localCovariance[i * 2 + 1];
547 Eigen::Matrix<float, 3, 1> globalPosition(
548 pxAux.globalPosition[i * 3], pxAux.globalPosition[i * 3 + 1],
549 pxAux.globalPosition[i * 3 + 2]);
550
551 std::vector<Identifier> RDOs;
552 RDOs.reserve(metadata->pcRdoIndex[i]);
553 // Cover RDO
554 for (unsigned int j = 0; j < metadata->pcRdoIndex[i]; ++j) {
555 RDOs.push_back(Identifier(pxAux.rdoList[rdoIndexCounter + j]));
556 }
557
558 rdoIndexCounter += metadata->pcRdoIndex[i];
559
560 pixelCl->setMeasurement<2>(pxAux.idHash[i], localPosition,
561 localCovariance);
562 pixelCl->setIdentifier(pxAux.id[i]);
563 pixelCl->setRDOlist(RDOs);
564 pixelCl->globalPosition() = globalPosition;
565 pixelCl->setChannelsInPhiEta(pxAux.channelsInPhi[i],
566 pxAux.channelsInEta[i]);
567 pixelCl->setWidthInEta(pxAux.widthInEta[i]);
568 }
569
570 return StatusCode::SUCCESS;
571 }
572
573 // --------------------------------------------------------------------
574 // proceed with the bulk copy method
575 // --------------------------------------------------------------------
576
577 ATH_MSG_DEBUG("You are running the bulk copy container creation method.");
578 if constexpr (enableBenchmark) Athena::Chrono chrono("BulkCopyMethod", m_chronoSvc.get());
579
580 // --------------------------
581 // Create the container and aux. container
582 // --------------------------
583 auto pixelCl = std::make_unique<xAOD::PixelClusterContainer>();
584 auto pixelClAux = std::make_unique<xAOD::PixelClusterAuxContainer>();
585 pixelCl->setStore(pixelClAux.get());
586
587 // Pre-allocate memory for all clusters in the AuxContainer
588 // and reserve the same space in the container.
589 const size_t nClusters = metadata->numOfPixelClusters;
590 pixelClAux->resize(nClusters);
591 pixelCl->reserve(nClusters);
592
593 // Now, push back the PixelCluster objects
594 // and create them all at once.
595 // Note, that no data is set yet,
596 // we will do that in the next step.
597 for (size_t i = 0; i < nClusters; ++i) {
598 pixelCl->push_back(std::make_unique<xAOD::PixelCluster>());
599 }
600
601 // --------------------------
602 // Prepare local buffers for each of the
603 // fixed-size attributes.
604 // --------------------------
605
606 std::vector<long unsigned int> identifierBuffer(nClusters);
607 std::vector<unsigned int> idHashBuffer(nClusters);
608 std::vector<std::array<float, 3>> gpBuffer(nClusters);
609 std::vector<float> localPosX(nClusters);
610 std::vector<float> localPosY(nClusters);
611 std::vector<float> localCovXX(nClusters);
612 std::vector<float> localCovYY(nClusters);
613 std::vector<int> totalToTBuffer(nClusters);
614 std::vector<float> widthInEtaBuffer(nClusters);
615 std::vector<int> channelsInPhiBuffer(nClusters);
616 std::vector<int> channelsInEtaBuffer(nClusters);
617
618 for (size_t i = 0; i < nClusters; ++i) {
619
620 // Fill the identifierBuffer
621 identifierBuffer[i] = pxAux.id[i];
622
623 // Fill the idHashBuffer
624 idHashBuffer[i] = pxAux.idHash[i];
625
626 // Fill the globalPositionBuffers
627 gpBuffer[i] = {
628 pxAux.globalPosition[3 * i],
629 pxAux.globalPosition[3 * i + 1],
630 pxAux.globalPosition[3 * i + 2],
631 };
632
633 // Fill the localPositionBuffers
634 localPosX[i] = pxAux.localPosition[2 * i];
635 localPosY[i] = pxAux.localPosition[2 * i + 1];
636
637 // Fill the localCovBuffer[i]
638 localCovXX[i] = pxAux.localCovariance[2 * i];
639 localCovYY[i] = pxAux.localCovariance[2 * i + 1];
640
641 // Fill the totalToTBuffer
642 totalToTBuffer[i] = pxAux.totalToT[i];
643
644 // Fill the widthInEtaBuffer
645 widthInEtaBuffer[i] = pxAux.widthInEta[i];
646
647 // Fill the channelsInPhiEtaBuffer
648 channelsInPhiBuffer[i] = pxAux.channelsInPhi[i];
649 channelsInEtaBuffer[i] = pxAux.channelsInEta[i];
650 }
651
652 // --------------------------
653 // Now, use SG::Accessors to do a bulk copy into
654 // the container memory.
655 // --------------------------
656
657 // FIXED-SIZE ATTRIBUTES
658 static const SG::Accessor<long unsigned int> idAcc("identifier");
659 static const SG::Accessor<unsigned int> idHashAcc("idHash");
660 static const SG::Accessor<float> localPosXAcc("localPositionX");
661 static const SG::Accessor<float> localPosYAcc("localPositionY");
662 static const SG::Accessor<float> localCovXXAcc("localCovarianceXX");
663 static const SG::Accessor<float> localCovYYAcc("localCovarianceYY");
664 static const SG::Accessor<int> totAcc("totalToT");
665 static const SG::Accessor<float> widthEtaAcc("widthInEta");
666 static const SG::Accessor<int> channelsInPhiAcc("channelsInPhi");
667 static const SG::Accessor<int> channelsInEtaAcc("channelsInEta");
668
669 // VARIABLE-LENGTH ATTRIBUTES
671 "globalPosition");
672
673 // Get spans into the container
674 auto idSpan = idAcc.getDataSpan(*pixelCl);
675 auto idHashSpan = idHashAcc.getDataSpan(*pixelCl);
676 auto locPosXSpan = localPosXAcc.getDataSpan(*pixelCl);
677 auto locPosYSpan = localPosYAcc.getDataSpan(*pixelCl);
678 auto locCovXXSpan = localCovXXAcc.getDataSpan(*pixelCl);
679 auto locCovYYSpan = localCovYYAcc.getDataSpan(*pixelCl);
680 auto totSpan = totAcc.getDataSpan(*pixelCl);
681 auto wEtaSpan = widthEtaAcc.getDataSpan(*pixelCl);
682 auto gpSpan = globalPosAcc.getDataSpan(*pixelCl);
683 auto channelsInPhiSpan = channelsInPhiAcc.getDataSpan(*pixelCl);
684 auto channelsInEtaSpan = channelsInEtaAcc.getDataSpan(*pixelCl);
685
686 // Bulk copy the fixed-size attributes
687 CxxUtils::copy_bounded(identifierBuffer, idSpan);
688 CxxUtils::copy_bounded(idHashBuffer, idHashSpan);
689 CxxUtils::copy_bounded(localPosX, locPosXSpan);
690 CxxUtils::copy_bounded(localPosY, locPosYSpan);
691 CxxUtils::copy_bounded(localCovXX, locCovXXSpan);
692 CxxUtils::copy_bounded(localCovYY, locCovYYSpan);
693 CxxUtils::copy_bounded(totalToTBuffer, totSpan);
694 CxxUtils::copy_bounded(widthInEtaBuffer, wEtaSpan);
695 CxxUtils::copy_bounded(gpBuffer, gpSpan);
696 CxxUtils::copy_bounded(channelsInPhiBuffer, channelsInPhiSpan);
697 CxxUtils::copy_bounded(channelsInEtaBuffer, channelsInEtaSpan);
698
699 // --------------------------
700 // Copy the variable-length data.
701 // We need to loop over the number of
702 // clusters to get access to each
703 // element.
704 // --------------------------
706 "rdoList");
707 auto rdoSpan = rdoListAcc.getDataSpan(*pixelCl);
708
709 int rdoIndexCounter = 0;
710 // loop over the clusters
711 for (size_t i = 0; i < nClusters; ++i) {
712 size_t nRDOs = metadata->pcRdoIndex[i];
713
714 // direct ref to destination vector
715 std::vector<unsigned long long> &rdosForThisCluster = rdoSpan[i];
716
717 // pre-size the vector
718 rdosForThisCluster.resize(nRDOs);
719
720 // direct element access
721 for (size_t j = 0; j < nRDOs; ++j) {
722 rdosForThisCluster[j] = pxAux.rdoList[rdoIndexCounter + j];
723 }
724 rdoIndexCounter += nRDOs;
725 }
726 // --------------------------
727 // Record the container + aux container into StoreGate,
728 // but now we do it AFTER filling the container!
729 // --------------------------
730
731 ATH_CHECK(pixelClustersHandle.record(std::move(pixelCl), std::move(pixelClAux)));
732
733 ATH_MSG_DEBUG("Bulk copy for fixed-size variables done.");
734 return StatusCode::SUCCESS;
735}
#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