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