ATLAS Offline Software
Loading...
Searching...
No Matches
xAODClusterMaker Class Reference

Creates xAOD pixel and strip cluster containers from FPGA input. More...

#include <xAODClusterMaker.h>

Inheritance diagram for xAODClusterMaker:
Collaboration diagram for xAODClusterMaker:

Public Member Functions

StatusCode initialize () override
 Initialise the tool.
StatusCode makeStripClusterContainer (const EFTrackingTransient::StripClusterAuxInput &scAux, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
 Make the strip cluster container.
StatusCode makeStripClusterContainer (const uint32_t *stripClusters, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
 Make the strip cluster container.
StatusCode makePixelClusterContainer (const EFTrackingTransient::PixelClusterAuxInput &pxAux, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
 Make the pixel cluster container.
StatusCode makePixelClusterContainer (const uint32_t *pixelClusters, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
 Make the pixel cluster container.

Private Attributes

SG::WriteHandleKey< xAOD::PixelClusterContainerm_pixelClustersKey
 Key for the pixel clusters container to be created.
SG::WriteHandleKey< xAOD::StripClusterContainerm_stripClustersKey
 Key for the strip clusters container to be created.
Gaudi::Property< bool > m_doBulkCopy {this, "DoBulkCopy", true, "Do bulk copy"}
 Do bulk copy method.
ServiceHandle< IChronoStatSvc > m_chronoSvc {this, "ChronoStatSvc", "ChronoStatSvc"}

Detailed Description

Creates xAOD pixel and strip cluster containers from FPGA input.

Definition at line 34 of file xAODClusterMaker.h.

Member Function Documentation

◆ initialize()

StatusCode xAODClusterMaker::initialize ( )
override

Initialise the tool.

Definition at line 45 of file xAODClusterMaker.cxx.

45 {
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}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
SG::WriteHandleKey< xAOD::StripClusterContainer > m_stripClustersKey
Key for the strip clusters container to be created.
SG::WriteHandleKey< xAOD::PixelClusterContainer > m_pixelClustersKey
Key for the pixel clusters container to be created.
ServiceHandle< IChronoStatSvc > m_chronoSvc

◆ makePixelClusterContainer() [1/2]

StatusCode xAODClusterMaker::makePixelClusterContainer ( const EFTrackingTransient::PixelClusterAuxInput & pxAux,
const EFTrackingTransient::Metadata * metadata,
const EventContext & ctx ) const

Make the pixel cluster container.

Parameters
pxAuxInput pixel cluster data
metadataInput metadata
ctx
Returns
StatusCode

Definition at line 511 of file xAODClusterMaker.cxx.

514 {
515 ATH_MSG_DEBUG("Making xAOD::PixelClusterContainer");
516
517
518 SG::WriteHandle<xAOD::PixelClusterContainer> pixelClustersHandle{m_pixelClustersKey, ctx};
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
670 static const SG::Accessor<std::array<float, 3>> globalPosAcc(
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 // --------------------------
705 static const SG::Accessor<std::vector<unsigned long long>> rdoListAcc(
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_MSG_DEBUG(x)
static const SG::AuxElement::Accessor< std::vector< Identifier::value_type > > rdoListAcc("rdoList")
static const SG::AuxElement::Accessor< std::array< float, 3 > > globalPosAcc("globalPosition")
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?
Gaudi::Property< bool > m_doBulkCopy
Do bulk copy method.
OutputIterator copy_bounded(InputIterator begi, InputIterator endi, OutputIterator bego, OutputIterator endo)
Copy a range with bounds restriction.
float j(const xAOD::IParticle &, const xAOD::TrackMeasurementValidation &hit, const Eigen::Matrix3d &jab_inv)
std::vector< unsigned long long > rdoList
constexpr bool enableBenchmark

◆ makePixelClusterContainer() [2/2]

StatusCode xAODClusterMaker::makePixelClusterContainer ( const uint32_t * pixelClusters,
const EFTrackingTransient::Metadata * metadata,
const EventContext & ctx ) const

Make the pixel cluster container.

Parameters
pixelClustersraw input from the EDM output
metadataInput metadata
ctx
Returns
StatusCode

Definition at line 282 of file xAODClusterMaker.cxx.

285 {
286 ATH_MSG_DEBUG("Making xAOD::PixelClusterContainer");
287
288
289 SG::WriteHandle<xAOD::PixelClusterContainer> pixelClustersHandle{m_pixelClustersKey, ctx};
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");
439 static const SG::Accessor<std::vector<unsigned long long>> rdoListAcc("rdoList");
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}
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...
std::string base
Definition hcg.cxx:81
constexpr uint32_t MAX_PIXEL_CLUSTERS
row
Appending html table to final .html summary file.
@ 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
@ globalZ
Definition HitInfo.h:39
setEventNumber uint32_t

◆ makeStripClusterContainer() [1/2]

StatusCode xAODClusterMaker::makeStripClusterContainer ( const EFTrackingTransient::StripClusterAuxInput & scAux,
const EFTrackingTransient::Metadata * metadata,
const EventContext & ctx ) const

Make the strip cluster container.

Parameters
scAuxInput strip cluster data
metadataInput metadata
ctx
Returns
StatusCode

Definition at line 231 of file xAODClusterMaker.cxx.

234 {
235 ATH_MSG_DEBUG("Making xAOD::StripClusterContainer");
236
237 SG::WriteHandle<xAOD::StripClusterContainer> stripClustersHandle{
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}
std::vector< unsigned long long > rdoList

◆ makeStripClusterContainer() [2/2]

StatusCode xAODClusterMaker::makeStripClusterContainer ( const uint32_t * stripClusters,
const EFTrackingTransient::Metadata * metadata,
const EventContext & ctx ) const

Make the strip cluster container.

Parameters
stripClustersraw input from the EDM output
metadataInput metadata
ctx
Returns
StatusCode

Definition at line 58 of file xAODClusterMaker.cxx.

61 {
62 ATH_MSG_DEBUG("Making xAOD::StripClusterContainer");
63
64 SG::WriteHandle<xAOD::StripClusterContainer> stripClustersHandle{m_stripClustersKey, ctx};
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");
176 static const SG::Accessor<std::vector<unsigned long long>> rdoListAcc("rdoList");
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}
constexpr uint32_t MAX_STRIP_CLUSTERS

Member Data Documentation

◆ m_chronoSvc

ServiceHandle<IChronoStatSvc> xAODClusterMaker::m_chronoSvc {this, "ChronoStatSvc", "ChronoStatSvc"}
private

Definition at line 106 of file xAODClusterMaker.h.

106{this, "ChronoStatSvc", "ChronoStatSvc"};

◆ m_doBulkCopy

Gaudi::Property<bool> xAODClusterMaker::m_doBulkCopy {this, "DoBulkCopy", true, "Do bulk copy"}
private

Do bulk copy method.

Definition at line 104 of file xAODClusterMaker.h.

104{this, "DoBulkCopy", true, "Do bulk copy"};

◆ m_pixelClustersKey

SG::WriteHandleKey<xAOD::PixelClusterContainer> xAODClusterMaker::m_pixelClustersKey
private
Initial value:
{
this, "PixelClusterContainerKey", "FPGAPixelClusters",
"Key for output pixel cluster container"}

Key for the pixel clusters container to be created.

Definition at line 95 of file xAODClusterMaker.h.

95 {
96 this, "PixelClusterContainerKey", "FPGAPixelClusters",
97 "Key for output pixel cluster container"};

◆ m_stripClustersKey

SG::WriteHandleKey<xAOD::StripClusterContainer> xAODClusterMaker::m_stripClustersKey
private
Initial value:
{
this, "StripClusterContainerKey", "FPGAStripClusters",
"Key for output strip cluster container"}

Key for the strip clusters container to be created.

Definition at line 100 of file xAODClusterMaker.h.

100 {
101 this, "StripClusterContainerKey", "FPGAStripClusters",
102 "Key for output strip cluster container"};

The documentation for this class was generated from the following files: