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 
107 
108  // using trick for fast insertion
109  std::vector< xAOD::SpacePoint* > preCollection;
110  preCollection.reserve(pixelClusters->size());
111  for ( std::size_t i(0); i<inputPixelClusterContainer->size(); ++i)
112  preCollection.push_back( new xAOD::SpacePoint() );
113  pixelSpacePoints->insert(pixelSpacePoints->end(), preCollection.begin(), preCollection.end());
114 
115 
116  std::map<IdentifierHash, std::vector<std::pair<unsigned int, unsigned int>>> cache_ranges;
117  int groupStartIdx = 0;
118  std::optional<IdentifierHash> groupIdHash = std::nullopt;
119 
120  //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)
121  //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
122  unsigned int spIdx = 0;
123 
124  for(unsigned int idx=0; idx<pixelClusters->size(); idx++){
125  const xAOD::PixelCluster* cluster = pixelClusters->at(idx);
126  IdentifierHash idHash = cluster->identifierHash();
127  if constexpr(useCache){
128  //check if the idHash is already in the cache
129  if(cacheHandle->tryAddFromCache(idHash)) continue;
130  }
131 
132  const InDetDD::SiDetectorElement* pixelElement = pixelElements->getDetectorElement(idHash);
133  if (pixelElement == nullptr) {
134  ATH_MSG_FATAL("Element pointer is nullptr");
135  return StatusCode::FAILURE;
136  }
137 
138  //get the index of the output spacepoint, when not using the cache this should be equal to the cluster index
139  unsigned int thisSpIdx = spIdx++;
140 
141  ATH_CHECK( m_spacePointMakerTool->producePixelSpacePoint(*cluster,
142  *pixelSpacePoints->at(thisSpIdx),
143  *pixelElement ) );
144 
145  if constexpr(useCache){
146  //check if the groupIdHash is defined if so and if it has changed then insert the range into the map
147  if(groupIdHash && ((*groupIdHash) != idHash)){
148  cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, thisSpIdx);
149  groupStartIdx = thisSpIdx;
150  }
151 
152  groupIdHash = idHash;
153  }
154  }
155 
156  //handle final idHash
157  if constexpr(useCache){
158  if(groupIdHash){
159  cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, spIdx);
160  }
161  }
162 
163  //finally resize the output for the actual number of inserted spacepoints
164  pixelSpacePoints->resize(spIdx);
165 
166 
167  if constexpr(useCache){
168  //add the ranges to the cache
169  for(auto idr: cache_ranges){
170  auto wh = cacheHandle->getWriteHandle(idr.first);
171  //check that item is not in the cache already (again)
172  if(wh.OnlineAndPresentInAnotherView()) continue;
173  auto ce = std::make_unique<Cache::CacheEntry<xAOD::SpacePoint>>(pixelSpacePoints, idr.second);
174  ATH_CHECK(wh.addOrDelete(std::move(ce)));
175  }
176  }
177 
178  nReceivedSPsPixel = pixelSpacePointContainer->size();
179  m_stat[kNSpacePoints] += nReceivedSPsPixel;
180  return StatusCode::SUCCESS;
181  }
182 
183 } //namespace