ATLAS Offline Software
StripSpacePointFormationAlgBase.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 
7 #include "xAODInDetMeasurement/StripClusterAuxContainer.h"
8 
9 #include "AthenaMonitoringKernel/Monitored.h"
10 #include "xAODInDetMeasurement/ContainerAccessor.h"
11 
12 namespace ActsTrk {
13 
14  //------------------------------------------------------------------------
15  template <bool useCache>
16  StripSpacePointFormationAlgBase<useCache>::StripSpacePointFormationAlgBase(const std::string& name,
17  ISvcLocator* pSvcLocator)
18  : AthReentrantAlgorithm(name, pSvcLocator)
19  {}
20 
21  //-----------------------------------------------------------------------
22  template <bool useCache>
23  StatusCode StripSpacePointFormationAlgBase<useCache>::initialize()
24  {
25  ATH_MSG_DEBUG( "Initializing " << name() << " ... " );
26 
27  ATH_CHECK( m_stripClusterContainerKey.initialize() );
28  ATH_CHECK( m_stripSpacePointContainerKey.initialize() );
29  ATH_CHECK( m_stripOverlapSpacePointContainerKey.initialize( m_processOverlapForStrip) );
30  ATH_CHECK( m_stripDetEleCollKey.initialize() );
31  ATH_CHECK( m_stripPropertiesKey.initialize() );
32 
33  ATH_CHECK( m_beamSpotKey.initialize() );
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  ATH_CHECK(m_OSPCache.initialize(useCache));
42  ATH_CHECK(m_OSPCacheBackend.initialize(useCache));
43 
44  return StatusCode::SUCCESS;
45  }
46 
47  template <bool useCache>
48  StatusCode StripSpacePointFormationAlgBase<useCache>::finalize()
49  {
50  ATH_MSG_INFO("Space Point Formation statistics" << std::endl << makeTable(m_stat,
51  std::array<std::string, kNStat>{
52  "Clusters",
53  "Space Points",
54  "Overlap Space Points"
55  }).columnWidth(10));
56 
57  return StatusCode::SUCCESS;
58  }
59 
60  //-------------------------------------------------------------------------
61  template <bool useCache>
62  StatusCode StripSpacePointFormationAlgBase<useCache>::execute (const EventContext& ctx) const
63  {
64  auto timer = Monitored::Timer<std::chrono::milliseconds>( "TIME_execute" );
65  auto timer_ca = Monitored::Timer<std::chrono::milliseconds>( "TIME_containerAccessor" );
66  auto mon_nCachedIdHashes = Monitored::Scalar<int>( "nCachedIdHashes" , 0 );
67  auto nReceivedSPsStrip = Monitored::Scalar<int>( "numStripSpacePoints" , 0 );
68  auto nReceivedSPsStripOverlap = Monitored::Scalar<int>( "numStripOverlapSpacePoints" , 0 );
69  auto mon = Monitored::Group( m_monTool, timer,timer_ca, nReceivedSPsStrip, nReceivedSPsStripOverlap, mon_nCachedIdHashes );
70 
71  SG::ReadHandle<xAOD::StripClusterContainer> inputStripClusterContainer( m_stripClusterContainerKey, ctx );
72  if (!inputStripClusterContainer.isValid()){
73  ATH_MSG_FATAL("xAOD::StripClusterContainer with key " << m_stripClusterContainerKey.key() << " is not available...");
74  return StatusCode::FAILURE;
75  }
76  const xAOD::StripClusterContainer* inputClusters = inputStripClusterContainer.cptr();
77  ATH_MSG_DEBUG("Retrieved " << inputClusters->size() << " clusters from container " << m_stripClusterContainerKey.key());
78  m_stat[kNClusters] += inputClusters->size();
79 
80  auto stripSpacePointContainer = SG::WriteHandle<xAOD::SpacePointContainer>( m_stripSpacePointContainerKey, ctx );
81  ATH_MSG_DEBUG( "--- Strip Space Point Container `" << m_stripSpacePointContainerKey.key() << "` created ..." );
82  ATH_CHECK( stripSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
83  std::make_unique<xAOD::SpacePointAuxContainer>() ));
84  xAOD::SpacePointContainer* spacePoints = stripSpacePointContainer.ptr();
85 
86 
87  xAOD::SpacePointContainer* overlapSpacePoints = nullptr;
88  SG::WriteHandle<xAOD::SpacePointContainer> stripOverlapSpacePointContainer;
89  if (m_processOverlapForStrip) {
90  stripOverlapSpacePointContainer = SG::WriteHandle<xAOD::SpacePointContainer>( m_stripOverlapSpacePointContainerKey, ctx );
91  ATH_MSG_DEBUG( "--- Strip Overlap Space Point Container `" << m_stripOverlapSpacePointContainerKey.key() << "` created ..." );
92  ATH_CHECK( stripOverlapSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
93  std::make_unique<xAOD::SpacePointAuxContainer>() ));
94  overlapSpacePoints = stripOverlapSpacePointContainer.ptr();
95  }
96 
97  Cache_WriteHandle cacheHandle;
98  Cache_WriteHandle overlapCacheHandle;
99  if constexpr(useCache){
100  cacheHandle = Cache_WriteHandle(m_SPCache, ctx);
101  auto updateHandle = Cache_BackendUpdateHandle(m_SPCacheBackend, ctx);
102  ATH_CHECK(updateHandle.isValid());
103  ATH_CHECK(cacheHandle.record(std::make_unique<Cache_IDC>(updateHandle.ptr())));
104  ATH_CHECK(cacheHandle.isValid());
105 
106  overlapCacheHandle = Cache_WriteHandle(m_OSPCache, ctx);
107  auto overlapUpdateHandle = Cache_BackendUpdateHandle(m_OSPCacheBackend, ctx);
108  ATH_CHECK(overlapUpdateHandle.isValid());
109  ATH_CHECK(overlapCacheHandle.record(std::make_unique<Cache_IDC>(overlapUpdateHandle.ptr())));
110  ATH_CHECK(overlapUpdateHandle.isValid());
111  }
112 
113 
114  // Early exit in case we have no clusters
115  // We still are saving an empty space point container in SG
116  if (inputClusters->empty()) {
117  ATH_MSG_DEBUG("No input clusters found, we stop space point formation");
118  return StatusCode::SUCCESS;
119  }
120 
121 
122  SG::ReadCondHandle<InDet::BeamSpotData> beamSpotHandle { m_beamSpotKey, ctx };
123  const InDet::BeamSpotData* beamSpot = *beamSpotHandle;
124  auto vertex = beamSpot->beamVtx().position();
125 
126 
127 
128  SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> stripDetEleHandle(m_stripDetEleCollKey, ctx);
129  const InDetDD::SiDetectorElementCollection* stripElements(*stripDetEleHandle);
130  if (not stripDetEleHandle.isValid() or stripElements==nullptr) {
131  ATH_MSG_FATAL(m_stripDetEleCollKey.fullKey() << " is not available.");
132  return StatusCode::FAILURE;
133  }
134 
135  SG::ReadCondHandle<InDet::SiElementPropertiesTable> stripProperties(m_stripPropertiesKey, ctx);
136  const InDet::SiElementPropertiesTable* properties = stripProperties.retrieve();
137  if (properties==nullptr) {
138  ATH_MSG_FATAL("Pointer of SiElementPropertiesTable (" << m_stripPropertiesKey.fullKey() << ") could not be retrieved");
139  return StatusCode::FAILURE;
140  }
141  timer_ca.start();
142  ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1> clusterAccessor ( *inputClusters, [](const xAOD::StripCluster& cl) { return cl.identifierHash();}, stripElements->size());
143  timer_ca.stop();
144 
145  unsigned int nCachedIdHashes = 0;
146 
147  if constexpr(useCache){
148  for(auto idHash: clusterAccessor.allIdentifiers()){
149  //obtain a write handle
150  auto cache_wh = cacheHandle->getWriteHandle(idHash);
151  auto overlap_cache_wh = overlapCacheHandle->getWriteHandle(idHash);
152  //check if already available
153  if(cache_wh.OnlineAndPresentInAnotherView()){
154  nCachedIdHashes += 1;
155  continue;
156  }
157 
158  unsigned int nsp = 0;
159 
160  for(auto rng: clusterAccessor.rangesForIdentifierDirect(idHash)){
161  nsp += (rng.second - rng.first);
162  }
163 
164  // Produce space points
165  std::vector<StripSP> sps;
166  std::vector<StripSP> osps;
167  //reserve the total number of clusters in the starting block
168  //at most will get one spacepoint for each
169  sps.reserve(nsp);
170  osps.reserve(nsp);
171 
172  ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
173  *inputClusters,
174  *properties,
175  *stripElements,
176  vertex,
177  sps,
178  osps,
179  m_processOverlapForStrip,
180  std::vector<IdentifierHash>{idHash},
181  clusterAccessor) );
182 
183  unsigned int sp_start_idx = spacePoints->size();
184 
185  fillSpacepoints(spacePoints, sps, inputClusters, sp_start_idx);
186 
187  //add to cache
188  ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(cache_wh, spacePoints, sp_start_idx, spacePoints->size()));
189 
190  if(overlapSpacePoints && m_processOverlapForStrip){
191  unsigned int osp_start_idx = overlapSpacePoints->size();
192  fillSpacepoints(overlapSpacePoints, osps, inputClusters, osp_start_idx);
193 
194  //add to cache
195  ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(overlap_cache_wh, overlapSpacePoints, osp_start_idx, overlapSpacePoints->size()));
196  }
197  }
198  }else{
199  // Produce space points without caching
200  std::vector<StripSP> sps;
201  std::vector<StripSP> osps;
202  sps.reserve(inputStripClusterContainer->size() * 0.5);
203  osps.reserve(inputStripClusterContainer->size() * 0.5);
204 
205  ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
206  *inputClusters,
207  *properties,
208  *stripElements,
209  vertex,
210  sps,
211  osps,
212  m_processOverlapForStrip,
213  clusterAccessor.allIdentifiers(),
214  clusterAccessor) );
215 
216  // using trick for fast insertion
217  spacePoints->reserve(sps.size());
218 
219  fillSpacepoints(spacePoints, sps, inputClusters);
220 
221  if(overlapSpacePoints && m_processOverlapForStrip){
222  overlapSpacePoints->reserve(osps.size());
223  fillSpacepoints(overlapSpacePoints, osps, inputClusters);
224  }
225  }
226 
227  nReceivedSPsStrip = stripSpacePointContainer->size();
228 
229  mon_nCachedIdHashes = nCachedIdHashes;
230 
231  if(m_processOverlapForStrip){
232  nReceivedSPsStripOverlap = overlapSpacePoints->size();
233  }else{
234  nReceivedSPsStripOverlap = 0; //avoid undefined value
235  }
236 
237  m_stat[kNSpacePoints] += nReceivedSPsStrip;
238  m_stat[kNOverlapSpacePoints] += nReceivedSPsStripOverlap;
239 
240  return StatusCode::SUCCESS;
241  }
242 
243  template <bool useCache>
244  void StripSpacePointFormationAlgBase<useCache>::fillSpacepoints(xAOD::SpacePointContainer* cont, std::vector<StripSP>& input, const xAOD::StripClusterContainer* inputClusters, unsigned int indexBase) const{
245  std::vector<xAOD::SpacePoint*> sp_collection;
246  sp_collection.reserve(input.size());
247  for (std::size_t i(0); i<input.size(); ++i)
248  sp_collection.push_back(new xAOD::SpacePoint());
249  cont->insert(cont->end(), sp_collection.begin(), sp_collection.end());
250 
251  // fill
252  for (std::size_t i(0); i<input.size(); ++i) {
253  auto& toAdd = input.at(i);
254 
255  // make link to Clusters
256  std::vector< const xAOD::UncalibratedMeasurement* > els(
257  {inputClusters->at(toAdd.measurementIndexes[0]),
258  inputClusters->at(toAdd.measurementIndexes[1])}
259  );
260  cont->at(indexBase+i)->setSpacePoint(toAdd.idHashes,
261  toAdd.globPos,
262  toAdd.cov_r,
263  toAdd.cov_z,
264  els,
265  toAdd.topHalfStripLength,
266  toAdd.bottomHalfStripLength,
267  toAdd.topStripDirection,
268  toAdd.bottomStripDirection,
269  toAdd.stripCenterDistance,
270  toAdd.topStripCenter);
271  }
272  }
273 }