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 46 of file xAODClusterMaker.cxx.

46 {
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}
#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 554 of file xAODClusterMaker.cxx.

557 {
558 ATH_MSG_DEBUG("Making xAOD::PixelClusterContainer");
559
560
561 SG::WriteHandle<xAOD::PixelClusterContainer> pixelClustersHandle{m_pixelClustersKey, ctx};
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_MSG_DEBUG(x)
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.
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:573
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 302 of file xAODClusterMaker.cxx.

305 {
306 ATH_MSG_DEBUG("Making xAOD::PixelClusterContainer");
307
308
309 SG::WriteHandle<xAOD::PixelClusterContainer> pixelClustersHandle{m_pixelClustersKey, ctx};
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}
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:83
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 251 of file xAODClusterMaker.cxx.

254 {
255 ATH_MSG_DEBUG("Making xAOD::StripClusterContainer");
256
257 SG::WriteHandle<xAOD::StripClusterContainer> stripClustersHandle{
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}
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 59 of file xAODClusterMaker.cxx.

62 {
63 ATH_MSG_DEBUG("Making xAOD::StripClusterContainer");
64
65 SG::WriteHandle<xAOD::StripClusterContainer> stripClustersHandle{m_stripClustersKey, ctx};
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)
197 xAOD::xAODInDetMeasurement::Utilities::JaggedVecEltCache<Identifier::value_type> rdoListCache(
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}
static const SG::AuxElement::Accessor< SG::JaggedVecElt< Identifier::value_type > > rdoListAcc()
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: