ATLAS Offline Software
PixelSpacePointFormationAlgBase.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "InDetReadoutGeometry/SiDetectorElement.h"
6 #include "PixelReadoutGeometry/PixelModuleDesign.h"
7 
8 #include "xAODInDetMeasurement/PixelClusterAuxContainer.h"
9 
10 #include "AthenaMonitoringKernel/Monitored.h"
11 #include "ActsInterop/TableUtils.h"
12 
13 #include <optional>
14 
15 namespace ActsTrk {
16 
17  //------------------------------------------------------------------------
18  template <bool useCache>
19  PixelSpacePointFormationAlgBase<useCache>::PixelSpacePointFormationAlgBase(const std::string& name,
20  ISvcLocator* pSvcLocator)
21  : AthReentrantAlgorithm(name, pSvcLocator)
22  {}
23 
24  //-----------------------------------------------------------------------
25  template <bool useCache>
26  StatusCode PixelSpacePointFormationAlgBase<useCache>::initialize()
27  {
28  ATH_MSG_DEBUG( "Initializing " << name() << " ... " );
29 
30  ATH_CHECK( m_pixelClusterContainerKey.initialize() );
31  ATH_CHECK( m_pixelSpacePointContainerKey.initialize() );
32  ATH_CHECK( m_pixelDetEleCollKey.initialize() );
33  ATH_CHECK( m_spacePointMakerTool.retrieve() );
34 
35  if ( not m_monTool.empty() )
36  ATH_CHECK( m_monTool.retrieve() );
37 
38  //caching
39  ATH_CHECK(m_SPCache.initialize(useCache));
40  ATH_CHECK(m_SPCacheBackend.initialize(useCache));
41 
42  return StatusCode::SUCCESS;
43  }
44 
45  template <bool useCache>
46  StatusCode PixelSpacePointFormationAlgBase<useCache>::finalize()
47  {
48  ATH_MSG_INFO("Space Point Formation statistics" << std::endl << makeTable(m_stat,
49  std::array<std::string, kNStat>{
50  "Clusters",
51  "Space Points"
52  }).columnWidth(10));
53 
54  return StatusCode::SUCCESS;
55  }
56 
57  //-------------------------------------------------------------------------
58  template <bool useCache>
59  StatusCode PixelSpacePointFormationAlgBase<useCache>::execute (const EventContext& ctx) const
60  {
61  auto timer = Monitored::Timer<std::chrono::milliseconds>( "TIME_execute" );
62  auto nReceivedSPsPixel = Monitored::Scalar<int>( "numPixSpacePoints" , 0 );
63  auto mon = Monitored::Group( m_monTool, timer, nReceivedSPsPixel );
64 
65  SG::ReadHandle<xAOD::PixelClusterContainer> inputPixelClusterContainer( m_pixelClusterContainerKey, ctx );
66  if (!inputPixelClusterContainer.isValid()){
67  ATH_MSG_FATAL("xAOD::PixelClusterContainer with key " << m_pixelClusterContainerKey.key() << " is not available...");
68  return StatusCode::FAILURE;
69  }
70  const xAOD::PixelClusterContainer *pixelClusters = inputPixelClusterContainer.cptr();
71  ATH_MSG_DEBUG("Retrieved " << pixelClusters->size() << " clusters from container " << m_pixelClusterContainerKey.key());
72  m_stat[kNClusters] += pixelClusters->size();
73 
74  auto pixelSpacePointContainer = SG::WriteHandle<xAOD::SpacePointContainer>( m_pixelSpacePointContainerKey, ctx );
75  ATH_MSG_DEBUG( "--- Pixel Space Point Container `" << m_pixelSpacePointContainerKey.key() << "` created ..." );
76  ATH_CHECK(pixelSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
77  std::make_unique<xAOD::SpacePointAuxContainer>() ));
78  xAOD::SpacePointContainer *pixelSpacePoints = pixelSpacePointContainer.ptr();
79 
80  Cache_WriteHandle cacheHandle;
81  if constexpr (useCache) {
82  cacheHandle = Cache_WriteHandle(m_SPCache, ctx);
83  auto updateHandle = Cache_BackendUpdateHandle(m_SPCacheBackend, ctx);
84  ATH_CHECK(updateHandle.isValid());
85  ATH_CHECK(cacheHandle.record(std::make_unique<Cache_IDC>(updateHandle.ptr())));
86  ATH_CHECK(cacheHandle.isValid());
87  }
88 
89  // Reserve space
90  pixelSpacePoints->reserve(pixelClusters->size());
91 
92  // Early exit in case we have no clusters
93  // We still are saving an empty space point container in SG
94  if (pixelClusters->empty()) {
95  ATH_MSG_DEBUG("No input clusters found, we stop space point formation");
96  return StatusCode::SUCCESS;
97  }
98 
99  SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> pixelDetEleHandle(m_pixelDetEleCollKey, ctx);
100  const InDetDD::SiDetectorElementCollection* pixelElements(*pixelDetEleHandle);
101  if (not pixelDetEleHandle.isValid() or pixelElements==nullptr) {
102  ATH_MSG_FATAL(m_pixelDetEleCollKey.fullKey() << " is not available.");
103  return StatusCode::FAILURE;
104  }
105 
106  // insertion of big collections
107  pixelSpacePoints->push_new(pixelClusters->size(), [] () {return new xAOD::SpacePoint();});
108 
109  std::map<IdentifierHash, std::vector<std::pair<unsigned int, unsigned int>>> cache_ranges;
110  int groupStartIdx = 0;
111  std::optional<IdentifierHash> groupIdHash = std::nullopt;
112 
113  //when using the cache some clusters can be skipped, this results in discontinuous spacepoints (but the unpopulated SP still exists and is getting filled into the cache and the output container)
114  //need to track the index of the spacepoints which are being inserted, so they are continuous and so that the output collection can be trimmed
115  unsigned int spIdx = 0;
116 
117  for(unsigned int idx=0; idx<pixelClusters->size(); idx++){
118  const xAOD::PixelCluster* cluster = pixelClusters->at(idx);
119  IdentifierHash idHash = cluster->identifierHash();
120  if constexpr(useCache){
121  //check if the idHash is already in the cache
122  if(cacheHandle->tryAddFromCache(idHash)) continue;
123  }
124 
125  const InDetDD::SiDetectorElement* pixelElement = pixelElements->getDetectorElement(idHash);
126  if (pixelElement == nullptr) {
127  ATH_MSG_FATAL("Element pointer is nullptr");
128  return StatusCode::FAILURE;
129  }
130 
131  //get the index of the output spacepoint, when not using the cache this should be equal to the cluster index
132  unsigned int thisSpIdx = spIdx++;
133 
134  ATH_CHECK( m_spacePointMakerTool->producePixelSpacePoint(*cluster,
135  *pixelSpacePoints->at(thisSpIdx),
136  *pixelElement ) );
137 
138  if constexpr(useCache){
139  //check if the groupIdHash is defined if so and if it has changed then insert the range into the map
140  if(groupIdHash && ((*groupIdHash) != idHash)){
141  cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, thisSpIdx);
142  groupStartIdx = thisSpIdx;
143  }
144 
145  groupIdHash = idHash;
146  }
147  }
148 
149  //handle final idHash
150  if constexpr(useCache){
151  if(groupIdHash){
152  cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, spIdx);
153  }
154  }
155 
156  //finally resize the output for the actual number of inserted spacepoints
157  pixelSpacePoints->resize(spIdx);
158 
159 
160  if constexpr(useCache){
161  //add the ranges to the cache
162  for(auto idr: cache_ranges){
163  auto wh = cacheHandle->getWriteHandle(idr.first);
164  //check that item is not in the cache already (again)
165  if(wh.OnlineAndPresentInAnotherView()) continue;
166  auto ce = std::make_unique<Cache::CacheEntry<xAOD::SpacePoint>>(pixelSpacePoints, idr.second);
167  ATH_CHECK(wh.addOrDelete(std::move(ce)));
168  }
169  }
170 
171  nReceivedSPsPixel = pixelSpacePointContainer->size();
172  m_stat[kNSpacePoints] += nReceivedSPsPixel;
173  return StatusCode::SUCCESS;
174  }
175 
176 } //namespace