ATLAS Offline Software
ClusterizationAlg.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 "AthenaMonitoringKernel/Monitored.h"
6 #include "xAODInDetMeasurement/ContainerAccessor.h"
7 #include "ActsInterop/TableUtils.h"
8 
9 namespace ActsTrk {
10 
11 template <typename IClusteringTool, bool useCache>
12 ClusterizationAlg<IClusteringTool, useCache>::ClusterizationAlg(const std::string& name,
13  ISvcLocator* pSvcLocator)
14  : AthReentrantAlgorithm(name, pSvcLocator)
15 {}
16 
17 template <typename IClusteringTool, bool useCache>
18 StatusCode ClusterizationAlg<IClusteringTool, useCache>::initialize()
19 {
20  ATH_MSG_DEBUG("Initializing " << name() << " ...");
21 
22  ATH_CHECK(m_rdoContainerKey.initialize());
23  ATH_CHECK(m_clusterContainerKey.initialize());
24  ATH_CHECK(m_roiCollectionKey.initialize());
25 
26  ATH_CHECK(m_detEleCollKey.initialize());
27  ATH_CHECK(m_detElStatus.initialize());
28 
29  ATH_CHECK(m_clusteringTool.retrieve());
30  ATH_CHECK(m_regionSelector.retrieve());
31 
32  ATH_CHECK(detStore()->retrieve(m_idHelper, m_idHelperName));
33 
34  // Monitoring
35  ATH_CHECK(m_monTool.retrieve(EnableTool{not m_monTool.empty()}));
36 
37  //caching
38  ATH_CHECK(m_ClusterCache.initialize(useCache));
39  ATH_CHECK(m_ClusterCacheBackend.initialize(useCache));
40 
41  return StatusCode::SUCCESS;
42 }
43 
44 template <typename IClusteringTool, bool useCache>
45 StatusCode ClusterizationAlg<IClusteringTool, useCache>::finalize()
46 {
47  ATH_MSG_INFO("Clusterization statistics" << std::endl << makeTable(m_stat,
48  std::array<std::string, kNStat>{
49  "RDOs",
50  "Clusters"
51  }).columnWidth(10));
52 
53  return StatusCode::SUCCESS;
54 }
55 
56 template <typename IClusteringTool, bool useCache>
57 StatusCode ClusterizationAlg<IClusteringTool, useCache>::execute(const EventContext& ctx) const
58 {
59  auto timer = Monitored::Timer<std::chrono::milliseconds>( "TIME_execute" );
60  auto timer_rdoReading = Monitored::Timer<std::chrono::milliseconds>( "TIME_readingRDOs" );
61  auto timer_processing = Monitored::Timer<std::chrono::milliseconds>( "TIME_clusterization" );
62  auto mon_nclusters = Monitored::Scalar<int>( "NClustersCreated" );
63  auto mon = Monitored::Group( m_monTool, timer, timer_rdoReading, timer_processing, mon_nclusters );
64 
65  timer_rdoReading.start();
66  SG::ReadHandle<RDOContainer> rdoContainerHandle = SG::makeHandle(m_rdoContainerKey, ctx);
67  ATH_CHECK(rdoContainerHandle.isValid());
68  const RDOContainer* rdoContainer = rdoContainerHandle.cptr();
69  timer_rdoReading.stop();
70 
71  SG::ReadHandle<TrigRoiDescriptorCollection> roiCollectionHandle = SG::makeHandle( m_roiCollectionKey, ctx );
72  ATH_CHECK(roiCollectionHandle.isValid());
73  const TrigRoiDescriptorCollection *roiCollection = roiCollectionHandle.cptr();
74 
75  SG::ReadCondHandle< InDetDD::SiDetectorElementCollection > detEleHandle = SG::makeHandle( m_detEleCollKey, ctx );
76  ATH_CHECK(detEleHandle.isValid());
77  const InDetDD::SiDetectorElementCollection* elements = detEleHandle.cptr();
78 
79  SG::ReadHandle< InDet::SiDetectorElementStatus > detEleStatusHandle = SG::makeHandle(m_detElStatus, ctx);
80  ATH_CHECK(detEleStatusHandle.isValid());
81  const InDet::SiDetectorElementStatus* detEleStatus = detEleStatusHandle.cptr();
82 
83  timer_processing.start();
84 
85  Cache_WriteHandle cacheHandle;
86  if constexpr (useCache) {
87  cacheHandle = Cache_WriteHandle(m_ClusterCache, ctx);
88  auto updateHandle = Cache_BackendUpdateHandle(m_ClusterCacheBackend, ctx);
89  ATH_CHECK(updateHandle.isValid());
90  ATH_CHECK(cacheHandle.record(std::make_unique<Cache_IDC>(updateHandle.ptr())));
91  ATH_CHECK(cacheHandle.isValid());
92  }
93 
94  // count number of elements and store some collections
95  std::vector<IdentifierHash> listOfIds;
96  listOfIds.reserve(elements->size());
97 
98  std::vector<bool> toBeProcessedIds(elements->size(), false);
99 
100  std::vector<const InDetDD::SiDetectorElement*> processedElements {};
101  processedElements.reserve(elements->size());
102  std::vector<typename IClusteringTool::ClusterCollection> clusterCollection {};
103  clusterCollection.reserve(elements->size());
104 
105  std::vector<Cache_IDCLock> idclocks;
106 
107  Acts::Ccl::ClusteringData data;
108 
109  // loop on ROIs
110  std::size_t nClusters = 0ul;
111  for (const auto* roi : *roiCollection) {
112  // get list of ids
113  listOfIds.clear();
114  m_regionSelector->lookup(ctx)->HashIDList(*roi, listOfIds);
115 
116  // loop on IDs
117  for (const IdentifierHash& id : listOfIds) {
118  if (not id.is_valid()) {
119  ATH_MSG_ERROR("Id hash is not valid: " << id);
120  return StatusCode::FAILURE;
121  }
122 
123  // check if already considered
124  if (toBeProcessedIds[id]) continue;
125  toBeProcessedIds[id] = true;
126 
127  Cache_IDCLock cache_wh;
128  if constexpr (useCache) {
129  //obtain a write handle
130  auto tmp = cacheHandle->getWriteHandle(id);
131  Cache_IDCLock::Swap(cache_wh, tmp);
132  //check if already available
133  if(cache_wh.OnlineAndPresentInAnotherView()) continue;
134  }
135 
136  const InDetDD::SiDetectorElement* element = elements->getDetectorElement(id);
137  if (not element) {
138  ATH_MSG_ERROR("Cannot retrieve Detector Element for id hash: " << id);
139  return StatusCode::FAILURE;
140  }
141 
142  // unpack RDOs and store them
143  const RawDataCollection* rdos = rdoContainer->indexFindPtr(id);
144  if (not rdos or rdos->empty()) {
145  continue;
146  }
147 
148  if constexpr (useCache) {
149  idclocks.push_back( std::move(cache_wh) );
150  }
151 
152  m_stat[kNRdo] += rdos->size();
153  // make ACTS clusters
154  ATH_CHECK( m_clusteringTool->clusterize(ctx,
155  *rdos,
156  *detEleStatus,
157  *element,
158  data,
159  clusterCollection) );
160  processedElements.push_back( element );
161  nClusters += clusterCollection.back().size();
162  } // loop on IDs
163  } // loop on ROIs
164 
165  mon_nclusters = nClusters;
166 
167  SG::WriteHandle<ClusterContainer> clusterHandle = SG::makeHandle(m_clusterContainerKey, ctx);
168  ATH_CHECK(clusterHandle.record( std::make_unique<ClusterContainer>(),
169  std::make_unique<ClusterAuxContainer>() ));
170  ClusterContainer *clusterContainer = clusterHandle.ptr();
171 
172  using xAODCluster_t = typename ClusterContainer::base_value_type;
173  clusterContainer->push_new(nClusters, [] () {return new xAODCluster_t();});
174 
175  // Fill the collection to xAOD format, computing necessary quantities
176  std::size_t xaodCounter = 0ul;
177  typename ClusterContainer::iterator finalElement = clusterContainer->end();
178  for (std::size_t i(0); i<clusterCollection.size(); ++i) {
179  const InDetDD::SiDetectorElement* element = processedElements[i];
180  typename IClusteringTool::ClusterCollection& actsClusters = clusterCollection[i];
181 
182  typename ClusterContainer::iterator itr = clusterContainer->begin() + xaodCounter;
183  if ( std::distance(itr, finalElement) < static_cast<long int>(actsClusters.size()) ) {
184  ATH_MSG_ERROR("Inconsistent size of clusters");
185  return StatusCode::FAILURE;
186  }
187 
188  ATH_CHECK( m_clusteringTool->makeClusters(ctx,
189  actsClusters,
190  *element,
191  itr) );
192 
193  if constexpr (useCache) {
194  // add to the cache
195  ATH_CHECK(Cache::Helper<BaseClusterType>::insert(idclocks[i],
196  clusterContainer,
197  xaodCounter,
198  xaodCounter + actsClusters.size()));
199  }
200 
201  xaodCounter += actsClusters.size();
202  }
203 
204  m_stat[kNClusters] += clusterContainer->size();
205  ATH_MSG_DEBUG("Clusters produced size: "<<clusterContainer->size());
206  timer_processing.stop();
207  return StatusCode::SUCCESS;
208 }
209 
210 } // namespace ActsTrk