ATLAS Offline Software
Public Member Functions | Private Attributes | List of all members
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. More...
 
StatusCode makeStripClusterContainer (const EFTrackingTransient::StripClusterAuxInput &scAux, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
 Make the strip cluster container. More...
 
StatusCode makeStripClusterContainer (const uint32_t *stripClusters, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
 Make the strip cluster container. More...
 
StatusCode makePixelClusterContainer (const EFTrackingTransient::PixelClusterAuxInput &pxAux, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
 Make the pixel cluster container. More...
 
StatusCode makePixelClusterContainer (const uint32_t *pixelClusters, const EFTrackingTransient::Metadata *metadata, const EventContext &ctx) const
 Make the pixel cluster container. More...
 

Private Attributes

SG::WriteHandleKey< xAOD::PixelClusterContainerm_pixelClustersKey
 Key for the pixel clusters container to be created. More...
 
SG::WriteHandleKey< xAOD::StripClusterContainerm_stripClustersKey
 Key for the strip clusters container to be created. More...
 
Gaudi::Property< bool > m_doBulkCopy {this, "DoBulkCopy", true, "Do bulk copy"}
 Do bulk copy method. More...
 
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 }

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

518  {
519  ATH_MSG_DEBUG("Making xAOD::PixelClusterContainer");
520 
521 
523 
524  if (!m_doBulkCopy) {
525  // --------------------------------------------------------------------
526  // proceed with the element-wise method
527  // --------------------------------------------------------------------
528  ATH_MSG_DEBUG("You are running the element-wise container creation method.");
529  if constexpr (enableBenchmark) Athena::Chrono chrono("ElementWiseMethod", m_chronoSvc.get());
530 
531  ATH_CHECK(pixelClustersHandle.record(
532  std::make_unique<xAOD::PixelClusterContainer>(),
533  std::make_unique<xAOD::PixelClusterAuxContainer>()));
534 
535  ATH_CHECK(pixelClustersHandle.isValid());
536  ATH_MSG_DEBUG("Container '" << m_pixelClustersKey << "' initialised");
537 
538  int rdoIndexCounter = 0;
539 
540  for (unsigned int i = 0; i < metadata->numOfPixelClusters; i++) {
541  // Push back numClusters of PixelCluster
542  auto pixelCl = pixelClustersHandle->push_back(
543  std::make_unique<xAOD::PixelCluster>());
544 
545  Eigen::Matrix<float, 2, 1> localPosition(
546  pxAux.localPosition[i * 2], pxAux.localPosition[i * 2 + 1]);
547  Eigen::Matrix<float, 2, 2> localCovariance;
548  localCovariance.setZero();
549  localCovariance(0, 0) = pxAux.localCovariance[i * 2];
550  localCovariance(1, 1) = pxAux.localCovariance[i * 2 + 1];
551  Eigen::Matrix<float, 3, 1> globalPosition(
552  pxAux.globalPosition[i * 3], pxAux.globalPosition[i * 3 + 1],
553  pxAux.globalPosition[i * 3 + 2]);
554 
555  std::vector<Identifier> RDOs;
556  RDOs.reserve(metadata->pcRdoIndex[i]);
557  // Cover RDO
558  for (unsigned int j = 0; j < metadata->pcRdoIndex[i]; ++j) {
559  RDOs.push_back(Identifier(pxAux.rdoList[rdoIndexCounter + j]));
560  }
561 
562  rdoIndexCounter += metadata->pcRdoIndex[i];
563 
564  pixelCl->setMeasurement<2>(pxAux.idHash[i], localPosition,
565  localCovariance);
566  pixelCl->setIdentifier(pxAux.id[i]);
567  pixelCl->setRDOlist(RDOs);
568  pixelCl->globalPosition() = globalPosition;
569  pixelCl->setTotalToT(pxAux.totalToT[i]);
570  pixelCl->setChannelsInPhiEta(pxAux.channelsInPhi[i],
571  pxAux.channelsInEta[i]);
572  pixelCl->setWidthInEta(pxAux.widthInEta[i]);
573  }
574 
575  return StatusCode::SUCCESS;
576  }
577 
578  // --------------------------------------------------------------------
579  // proceed with the bulk copy method
580  // --------------------------------------------------------------------
581 
582  ATH_MSG_DEBUG("You are running the bulk copy container creation method.");
583  if constexpr (enableBenchmark) Athena::Chrono chrono("BulkCopyMethod", m_chronoSvc.get());
584 
585  // --------------------------
586  // Create the container and aux. container
587  // --------------------------
588  auto pixelCl = std::make_unique<xAOD::PixelClusterContainer>();
589  auto pixelClAux = std::make_unique<xAOD::PixelClusterAuxContainer>();
590  pixelCl->setStore(pixelClAux.get());
591 
592  // Pre-allocate memory for all clusters in the AuxContainer
593  // and reserve the same space in the container.
594  const size_t nClusters = metadata->numOfPixelClusters;
595  pixelClAux->resize(nClusters);
596  pixelCl->reserve(nClusters);
597 
598  // Now, push back the PixelCluster objects
599  // and create them all at once.
600  // Note, that no data is set yet,
601  // we will do that in the next step.
602  for (size_t i = 0; i < nClusters; ++i) {
603  pixelCl->push_back(std::make_unique<xAOD::PixelCluster>());
604  }
605 
606  // --------------------------
607  // Prepare local buffers for each of the
608  // fixed-size attributes.
609  // --------------------------
610 
611  std::vector<long unsigned int> identifierBuffer(nClusters);
612  std::vector<unsigned int> idHashBuffer(nClusters);
613  std::vector<std::array<float, 3>> gpBuffer(nClusters);
614  std::vector<float> localPosX(nClusters);
615  std::vector<float> localPosY(nClusters);
616  std::vector<float> localCovXX(nClusters);
617  std::vector<float> localCovYY(nClusters);
618  std::vector<int> totalToTBuffer(nClusters);
619  std::vector<float> widthInEtaBuffer(nClusters);
620  std::vector<int> channelsInPhiBuffer(nClusters);
621  std::vector<int> channelsInEtaBuffer(nClusters);
622 
623  for (size_t i = 0; i < nClusters; ++i) {
624 
625  // Fill the identifierBuffer
626  identifierBuffer[i] = pxAux.id[i];
627 
628  // Fill the idHashBuffer
629  idHashBuffer[i] = pxAux.idHash[i];
630 
631  // Fill the globalPositionBuffers
632  gpBuffer[i] = {
633  pxAux.globalPosition[3 * i],
634  pxAux.globalPosition[3 * i + 1],
635  pxAux.globalPosition[3 * i + 2],
636  };
637 
638  // Fill the localPositionBuffers
639  localPosX[i] = pxAux.localPosition[2 * i];
640  localPosY[i] = pxAux.localPosition[2 * i + 1];
641 
642  // Fill the localCovBuffer[i]
643  localCovXX[i] = pxAux.localCovariance[2 * i];
644  localCovYY[i] = pxAux.localCovariance[2 * i + 1];
645 
646  // Fill the totalToTBuffer
647  totalToTBuffer[i] = pxAux.totalToT[i];
648 
649  // Fill the widthInEtaBuffer
650  widthInEtaBuffer[i] = pxAux.widthInEta[i];
651 
652  // Fill the channelsInPhiEtaBuffer
653  channelsInPhiBuffer[i] = pxAux.channelsInPhi[i];
654  channelsInEtaBuffer[i] = pxAux.channelsInEta[i];
655  }
656 
657  // --------------------------
658  // Now, use SG::Accessors to do a bulk copy into
659  // the container memory.
660  // --------------------------
661 
662  // FIXED-SIZE ATTRIBUTES
663  static const SG::Accessor<long unsigned int> idAcc("identifier");
664  static const SG::Accessor<unsigned int> idHashAcc("idHash");
665  static const SG::Accessor<float> localPosXAcc("localPositionX");
666  static const SG::Accessor<float> localPosYAcc("localPositionY");
667  static const SG::Accessor<float> localCovXXAcc("localCovarianceXX");
668  static const SG::Accessor<float> localCovYYAcc("localCovarianceYY");
669  static const SG::Accessor<int> totAcc("totalToT");
670  static const SG::Accessor<float> widthEtaAcc("widthInEta");
671  static const SG::Accessor<int> channelsInPhiAcc("channelsInPhi");
672  static const SG::Accessor<int> channelsInEtaAcc("channelsInEta");
673 
674  // VARIABLE-LENGTH ATTRIBUTES
675  static const SG::Accessor<std::array<float, 3>> globalPosAcc(
676  "globalPosition");
677 
678  // Get spans into the container
679  auto idSpan = idAcc.getDataSpan(*pixelCl);
680  auto idHashSpan = idHashAcc.getDataSpan(*pixelCl);
681  auto locPosXSpan = localPosXAcc.getDataSpan(*pixelCl);
682  auto locPosYSpan = localPosYAcc.getDataSpan(*pixelCl);
683  auto locCovXXSpan = localCovXXAcc.getDataSpan(*pixelCl);
684  auto locCovYYSpan = localCovYYAcc.getDataSpan(*pixelCl);
685  auto totSpan = totAcc.getDataSpan(*pixelCl);
686  auto wEtaSpan = widthEtaAcc.getDataSpan(*pixelCl);
687  auto gpSpan = globalPosAcc.getDataSpan(*pixelCl);
688  auto channelsInPhiSpan = channelsInPhiAcc.getDataSpan(*pixelCl);
689  auto channelsInEtaSpan = channelsInEtaAcc.getDataSpan(*pixelCl);
690 
691  // Bulk copy the fixed-size attributes
692  CxxUtils::copy_bounded(identifierBuffer, idSpan);
693  CxxUtils::copy_bounded(idHashBuffer, idHashSpan);
694  CxxUtils::copy_bounded(localPosX, locPosXSpan);
695  CxxUtils::copy_bounded(localPosY, locPosYSpan);
696  CxxUtils::copy_bounded(localCovXX, locCovXXSpan);
697  CxxUtils::copy_bounded(localCovYY, locCovYYSpan);
698  CxxUtils::copy_bounded(totalToTBuffer, totSpan);
699  CxxUtils::copy_bounded(widthInEtaBuffer, wEtaSpan);
700  CxxUtils::copy_bounded(gpBuffer, gpSpan);
701  CxxUtils::copy_bounded(channelsInPhiBuffer, channelsInPhiSpan);
702  CxxUtils::copy_bounded(channelsInEtaBuffer, channelsInEtaSpan);
703 
704  // --------------------------
705  // Copy the variable-length data.
706  // We need to loop over the number of
707  // clusters to get access to each
708  // element.
709  // --------------------------
710  static const SG::Accessor<std::vector<unsigned long long>> rdoListAcc(
711  "rdoList");
712  auto rdoSpan = rdoListAcc.getDataSpan(*pixelCl);
713 
714  int rdoIndexCounter = 0;
715  // loop over the clusters
716  for (size_t i = 0; i < nClusters; ++i) {
717  size_t nRDOs = metadata->pcRdoIndex[i];
718 
719  // direct ref to destination vector
720  std::vector<unsigned long long> &rdosForThisCluster = rdoSpan[i];
721 
722  // pre-size the vector
723  rdosForThisCluster.resize(nRDOs);
724 
725  // direct element access
726  for (size_t j = 0; j < nRDOs; ++j) {
727  rdosForThisCluster[j] = pxAux.rdoList[rdoIndexCounter + j];
728  }
729  rdoIndexCounter += nRDOs;
730  }
731  // --------------------------
732  // Record the container + aux container into StoreGate,
733  // but now we do it AFTER filling the container!
734  // --------------------------
735 
736  ATH_CHECK(pixelClustersHandle.record(std::move(pixelCl), std::move(pixelClAux)));
737 
738  ATH_MSG_DEBUG("Bulk copy for fixed-size variables done.");
739  return StatusCode::SUCCESS;
740 }

◆ 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 
290 
291  if (!m_doBulkCopy) {
292  // --------------------------------------------------------------------
293  // proceed with the element-wise method
294  // --------------------------------------------------------------------
295  ATH_CHECK(pixelClustersHandle.record(std::make_unique<xAOD::PixelClusterContainer>(),std::make_unique<xAOD::PixelClusterAuxContainer>()));
296 
297  ATH_CHECK(pixelClustersHandle.isValid());
298 
299  for (unsigned int i = 0; i < metadata->numOfPixelClusters; i++)
300  {
301  // Push back numClusters of StripCluster
302  auto pixelCl = pixelClustersHandle->push_back(std::make_unique<xAOD::PixelCluster>());
303 
304  int row = 0; // idhash
305  unsigned int idHash = pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16];
306  row = 1; // id
307  unsigned long long id = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
308 
309  std::vector<Identifier> RDOs;
310  row = 3; // rdo w1
311  unsigned long long rdo = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
312  if (rdo) RDOs.push_back(Identifier(rdo));
313 
314  row = 5; // rdo w2
315  rdo = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
316  if (rdo) RDOs.push_back(Identifier(rdo));
317 
318  row = 7; // rdo w3
319  rdo = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
320  if (rdo) RDOs.push_back(Identifier(rdo));
321 
322  row = 9; // rdo w4
323  rdo = to64 (pixelClusters + row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i*2 + 16);
324  if (rdo) RDOs.push_back(Identifier(rdo));
325 
326  Eigen::Matrix<float, 2, 1> localPosition;
327  Eigen::Matrix<float, 2, 2> localCovariance;
328  localCovariance.setZero();
329  row = 11; // local x
330  localPosition(0 , 0) = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
331 
332  row = 12; // local y
333  localPosition(1 , 1) = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
334 
335  row = 13; // local covariance xx
336  localCovariance(0, 0) = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
337 
338  row = 14; // local covariance yy
339  localCovariance(1, 1) = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
340 
341  row = 15; // global x
342  float globalX = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
343 
344  row = 16; // global y
345  float globalY = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
346 
347  row = 17; // global
348  float globalZ = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
349 
350  row = 18; // channels in phi
351  int channelsInPhi = pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16];
352 
353  row = 19; // channels in eta
354  int channelsInEta = pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16];
355 
356  row = 20; // width in eta
357  double widthInEta = std::bit_cast<float>(pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16]);
358 
359  row = 21; // total ToT
360  int totalToT = pixelClusters[row * EFTrackingTransient::MAX_PIXEL_CLUSTERS + i + 16];
361 
362  Eigen::Matrix<float, 3, 1> globalPosition(globalX, globalY, globalZ);
363 
364  pixelCl->setMeasurement<2>(idHash, localPosition,localCovariance);
365  pixelCl->setIdentifier(id);
366  pixelCl->setRDOlist(RDOs);
367  pixelCl->globalPosition() = globalPosition;
368  pixelCl->setTotalToT(totalToT);
369  pixelCl->setChannelsInPhiEta(channelsInPhi, channelsInEta);
370  pixelCl->setWidthInEta(widthInEta);
371  }
372  return StatusCode::SUCCESS;
373  }
374 
375  ATH_MSG_DEBUG("Doing bulk copy (optimized)");
376  // --------------------------
377  // Create the container and aux. container
378  // --------------------------
379  const size_t nClusters = metadata->numOfPixelClusters;
380  DataPool<xAOD::PixelCluster> pixelPool{ctx};
381  pixelPool.reserve(nClusters);
382  auto pixelCl = std::make_unique<xAOD::PixelClusterContainer>(SG::VIEW_ELEMENTS, SG::ALWAYS_TRACK_INDICES);
383  {
384  if constexpr (enableBenchmark) Athena::Chrono chrono("Pixel object creating", m_chronoSvc.get());
385  pixelCl->push_new(nClusters, [&pixelPool]() { return pixelPool.nextElementPtr(); });
386  }
387  auto pixelClAux = std::make_unique<xAOD::PixelClusterAuxContainer>();
388  pixelClAux->resize(nClusters);
389  pixelCl->setStore(pixelClAux.get());
390 
391  // --------------------------
392  // Access fixed-size attributes directly (rows/offsets as in !m_doBulkCopy)
393  // --------------------------
395  const size_t offset = 16;
396 
397  // Treat the raw column-major buffer as 32-bit words; 64-bit values span two words.
398  const uint32_t* base = pixelClusters;
399 
400  auto load_u64 = [&](size_t row, size_t idx) -> uint64_t {
401  const uint32_t* p32 = base + row * N + offset + 2 * idx;
402  return *reinterpret_cast<const uint64_t*>(p32);
403  };
404  auto load_f32 = [&](size_t row, size_t idx) -> float {
405  return std::bit_cast<float>(*(base + row * N + offset + idx));
406  };
407  auto load_u32 = [&](size_t row, size_t idx) -> uint32_t {
408  return *(base + row * N + offset + idx);
409  };
410 
411  // Row layout (must match the element-wise path)
412  constexpr size_t ROW_idHash = 0;
413  constexpr size_t ROW_identifier = 1; // u64
414  constexpr size_t ROW_rdo_w1 = 3; // u64
415  constexpr size_t ROW_rdo_w2 = 5; // u64
416  constexpr size_t ROW_rdo_w3 = 7; // u64
417  constexpr size_t ROW_rdo_w4 = 9; // u64
418  constexpr size_t ROW_localX = 11; // f32
419  constexpr size_t ROW_localY = 12; // f32
420  constexpr size_t ROW_covXX = 13; // f32
421  constexpr size_t ROW_covYY = 14; // f32
422  constexpr size_t ROW_gpX = 15; // f32
423  constexpr size_t ROW_gpY = 16; // f32
424  constexpr size_t ROW_gpZ = 17; // f32
425  constexpr size_t ROW_channelsPhi = 18; // i32
426  constexpr size_t ROW_channelsEta = 19; // i32
427  constexpr size_t ROW_widthEta = 20; // f32
428  constexpr size_t ROW_totalToT = 21; // i32
429 
430  // --------------------------
431  // Precompute spans into aux data store (types aligned with !m_doBulkCopy behavior)
432  // --------------------------
433  if (nClusters > 0) {
434  static const SG::Accessor<unsigned int> idHashAcc("identifierHash");
435  static const SG::Accessor<unsigned long> idAcc("identifier");
436  static const SG::Accessor<std::array<float, 3>> gpAcc("globalPosition");
437  static const SG::Accessor<std::array<float, 2>> locPosAcc("localPositionDim2");
438  static const SG::Accessor<std::array<float, 4>> locCovAcc("localCovarianceDim2");
439  static const SG::Accessor<int> totalToTAcc("totalToT");
440  static const SG::Accessor<int> channelsPhiAcc("channelsInPhi");
441  static const SG::Accessor<int> channelsEtaAcc("channelsInEta");
442  static const SG::Accessor<float> widthEtaAcc("widthInEta");
443  static const SG::Accessor<std::vector<unsigned long long>> rdoListAcc("rdoList");
444 
445 
446  auto idHashSpan = idHashAcc.getDataSpan(*pixelCl);
447  auto idSpan = idAcc.getDataSpan(*pixelCl);
448  auto gpSpan = gpAcc.getDataSpan(*pixelCl);
449  auto locPosSpan = locPosAcc.getDataSpan(*pixelCl);
450  auto locCovSpan = locCovAcc.getDataSpan(*pixelCl);
451  auto totalToTSpan = totalToTAcc.getDataSpan(*pixelCl);
452  auto channelsPhiSpan = channelsPhiAcc.getDataSpan(*pixelCl);
453  auto channelsEtaSpan = channelsEtaAcc.getDataSpan(*pixelCl);
454  auto widthEtaSpan = widthEtaAcc.getDataSpan(*pixelCl);
455  auto rdoSpan = rdoListAcc.getDataSpan(*pixelCl);
456 
457  // --------------------------
458  // Vectorized bulk assignments
459  // --------------------------
460  {
461  if constexpr (enableBenchmark) Athena::Chrono chrono("Pixel assignments", m_chronoSvc.get());
462  for (size_t i = 0; i < nClusters; ++i) {
463  // Basic ids
464  idHashSpan[i] = static_cast<unsigned int>(load_u32(ROW_idHash, i));
465  idSpan[i] = static_cast<unsigned long long>(load_u64(ROW_identifier, i));
466 
467  // Local position (2x1)
468  locPosSpan[i][0] = load_f32(ROW_localX, i);
469  locPosSpan[i][1] = load_f32(ROW_localY, i);
470 
471  // Local covariance (2x2) flattened as [xx, xy, yx, yy]
472  locCovSpan[i][0] = load_f32(ROW_covXX, i);
473  locCovSpan[i][3] = load_f32(ROW_covYY, i);
474 
475  // Global position
476  gpSpan[i][0] = load_f32(ROW_gpX, i);
477  gpSpan[i][1] = load_f32(ROW_gpY, i);
478  gpSpan[i][2] = load_f32(ROW_gpZ, i);
479 
480  // Discrete/int attrs
481  channelsPhiSpan[i] = static_cast<int>(load_u32(ROW_channelsPhi, i));
482  channelsEtaSpan[i] = static_cast<int>(load_u32(ROW_channelsEta, i));
483  widthEtaSpan[i] = load_f32(ROW_widthEta, i);
484  totalToTSpan[i] = static_cast<int>(load_u32(ROW_totalToT, i));
485 
486  // RDOs (up to 4)
487  auto& rdoList = rdoSpan[i];
488  rdoList.reserve(4);
489  uint64_t r1 = load_u64(ROW_rdo_w1, i);
490  uint64_t r2 = load_u64(ROW_rdo_w2, i);
491  uint64_t r3 = load_u64(ROW_rdo_w3, i);
492  uint64_t r4 = load_u64(ROW_rdo_w4, i);
493  if (r1) rdoList.emplace_back(r1);
494  if (r2) rdoList.emplace_back(r2);
495  if (r3) rdoList.emplace_back(r3);
496  if (r4) rdoList.emplace_back(r4);
497  }
498  }
499  }
500 
501  {
502  if constexpr (enableBenchmark) Athena::Chrono chrono("Pixel Copy", m_chronoSvc.get());
503  ATH_CHECK(pixelClustersHandle.record(std::move(pixelCl), std::move(pixelClAux)));
504  }
505 
506  return StatusCode::SUCCESS;
507 
508 
509 
510  return StatusCode::SUCCESS;
511 }

◆ 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 
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 }

◆ 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 
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 }

Member Data Documentation

◆ m_chronoSvc

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

Definition at line 106 of file xAODClusterMaker.h.

◆ 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.

◆ 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.

◆ 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.


The documentation for this class was generated from the following files:
base
std::string base
Definition: hcg.cxx:81
EFTrackingTransient::PixelClusterAuxInput::localPosition
std::vector< float > localPosition
Definition: EFTrackingTransient.h:241
xAODClusterMaker::m_pixelClustersKey
SG::WriteHandleKey< xAOD::PixelClusterContainer > m_pixelClustersKey
Key for the pixel clusters container to be created.
Definition: xAODClusterMaker.h:95
EFTrackingTransient::PixelClusterAuxInput::channelsInEta
std::vector< int > channelsInEta
Definition: EFTrackingTransient.h:246
xAODClusterMaker::m_doBulkCopy
Gaudi::Property< bool > m_doBulkCopy
Do bulk copy method.
Definition: xAODClusterMaker.h:104
EFTrackingTransient::StripClusterAuxInput::globalPosition
std::vector< float > globalPosition
Definition: EFTrackingTransient.h:228
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
SG::VIEW_ELEMENTS
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
Definition: OwnershipPolicy.h:18
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
SG::ALWAYS_TRACK_INDICES
@ ALWAYS_TRACK_INDICES
Always track indices, regardless of the setting of the ownership policy.
Definition: IndexTrackingPolicy.h:43
EFTrackingTransient::StripClusterAuxInput::localCovariance
std::vector< float > localCovariance
Definition: EFTrackingTransient.h:225
TRT::Hit::globalZ
@ globalZ
Definition: HitInfo.h:39
DataPool::reserve
void reserve(unsigned int size)
Set the desired capacity.
keylayer_zslicemap.row
row
Definition: keylayer_zslicemap.py:155
JetTiledMap::N
@ N
Definition: TiledEtaPhiMap.h:44
MCP::ScaleSmearParam::r2
@ r2
EFTrackingTransient::StripClusterAuxInput::rdoList
std::vector< unsigned long long > rdoList
Definition: EFTrackingTransient.h:229
python.checkMetadata.metadata
metadata
Definition: checkMetadata.py:175
xAODClusterMaker::m_stripClustersKey
SG::WriteHandleKey< xAOD::StripClusterContainer > m_stripClustersKey
Key for the strip clusters container to be created.
Definition: xAODClusterMaker.h:100
Athena::Chrono
Exception-safe IChronoSvc caller.
Definition: Chrono.h:50
EFTrackingTransient::PixelClusterAuxInput::rdoList
std::vector< unsigned long long > rdoList
Definition: EFTrackingTransient.h:244
lumiFormat.i
int i
Definition: lumiFormat.py:85
EFTrackingTransient::PixelClusterAuxInput::localCovariance
std::vector< float > localCovariance
Definition: EFTrackingTransient.h:242
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
EFTrackingTransient::StripClusterAuxInput::idHash
std::vector< unsigned int > idHash
Definition: EFTrackingTransient.h:226
CxxUtils::copy_bounded
OutputIterator copy_bounded(InputIterator begi, InputIterator endi, OutputIterator bego, OutputIterator endo)
Copy a range with bounds restriction.
Definition: copy_bounded.h:79
EFTrackingTransient::PixelClusterAuxInput::totalToT
std::vector< int > totalToT
Definition: EFTrackingTransient.h:249
xAOD::uint64_t
uint64_t
Definition: EventInfo_v1.cxx:123
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
EFTrackingTransient::MAX_PIXEL_CLUSTERS
constexpr uint32_t MAX_PIXEL_CLUSTERS
Definition: EFTrackingTransient.h:27
enableBenchmark
constexpr bool enableBenchmark
Definition: xAODClusterMaker.cxx:13
EFTrackingTransient::PixelClusterAuxInput::idHash
std::vector< unsigned int > idHash
Definition: EFTrackingTransient.h:240
EFTrackingTransient::StripClusterAuxInput::localPosition
std::vector< float > localPosition
Definition: EFTrackingTransient.h:224
EFTrackingTransient::PixelClusterAuxInput::channelsInPhi
std::vector< int > channelsInPhi
Definition: EFTrackingTransient.h:245
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
EFTrackingTransient::PixelClusterAuxInput::id
std::vector< long unsigned int > id
Definition: EFTrackingTransient.h:239
EFTrackingTransient::PixelClusterAuxInput::widthInEta
std::vector< float > widthInEta
Definition: EFTrackingTransient.h:247
EFTrackingTransient::MAX_STRIP_CLUSTERS
constexpr uint32_t MAX_STRIP_CLUSTERS
Definition: EFTrackingTransient.h:28
EFTrackingTransient::PixelClusterAuxInput::globalPosition
std::vector< float > globalPosition
Definition: EFTrackingTransient.h:243
EFTrackingTransient::StripClusterAuxInput::id
std::vector< long unsigned int > id
Definition: EFTrackingTransient.h:227
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
DataPool
a typed memory pool that saves time spent allocation small object. This is typically used by containe...
Definition: DataPool.h:63
EFTrackingTransient::StripClusterAuxInput::channelsInPhi
std::vector< int > channelsInPhi
Definition: EFTrackingTransient.h:230
xAODClusterMaker::m_chronoSvc
ServiceHandle< IChronoStatSvc > m_chronoSvc
Definition: xAODClusterMaker.h:106
MCP::ScaleSmearParam::r1
@ r1
Identifier
Definition: IdentifierFieldParser.cxx:14