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 objects are available in the cache already (function has a sideeffect of including them in this container if they are)
153  bool fill_sp = true;
154  bool fill_osp = true;
155  //check if already available
156  if(cache_wh.OnlineAndPresentInAnotherView()){
157  nCachedIdHashes += 1;
158  fill_sp = false;
159  }
160 
161  //avoid calling a cache function if not going to process osp
162  if(m_processOverlapForStrip){
163  fill_osp = !overlap_cache_wh.OnlineAndPresentInAnotherView();
164  }else{
165  fill_osp = false;
166  }
167 
168  //check if we have something to do
169  if(!(fill_sp || fill_osp)){
170  continue;
171  }
172 
173  unsigned int nsp = 0;
174 
175  for(auto rng: clusterAccessor.rangesForIdentifierDirect(idHash)){
176  nsp += (rng.second - rng.first);
177  }
178 
179  // Produce space points
180  std::vector<StripSP> sps;
181  std::vector<StripSP> osps;
182  //reserve the total number of clusters in the starting block
183  //at most will get one spacepoint for two clusters
184  sps.reserve(nsp*0.5);
185  osps.reserve(nsp*0.5);
186 
187  ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
188  *inputClusters,
189  *properties,
190  *stripElements,
191  vertex,
192  sps,
193  osps,
194  m_processOverlapForStrip,
195  std::vector<IdentifierHash>{idHash},
196  clusterAccessor) );
197 
198 
199 
200  //cannot insert twice so need to check if we already have something
201  if(fill_sp){
202  unsigned int sp_start_idx = spacePoints->size();
203  fillSpacepoints(spacePoints, sps, inputClusters, sp_start_idx);
204 
205  //add to cache
206  ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(cache_wh, spacePoints, sp_start_idx, spacePoints->size()));
207  }
208 
209  if(overlapSpacePoints && m_processOverlapForStrip && fill_osp){
210  unsigned int osp_start_idx = overlapSpacePoints->size();
211  fillSpacepoints(overlapSpacePoints, osps, inputClusters, osp_start_idx);
212 
213  //add to cache
214  ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(overlap_cache_wh, overlapSpacePoints, osp_start_idx, overlapSpacePoints->size()));
215  }
216  }
217  }else{
218  // Produce space points without caching
219  std::vector<StripSP> sps;
220  std::vector<StripSP> osps;
221  sps.reserve(inputStripClusterContainer->size() * 0.5);
222  osps.reserve(inputStripClusterContainer->size() * 0.5);
223 
224  ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
225  *inputClusters,
226  *properties,
227  *stripElements,
228  vertex,
229  sps,
230  osps,
231  m_processOverlapForStrip,
232  clusterAccessor.allIdentifiers(),
233  clusterAccessor) );
234 
235  // using trick for fast insertion
236  spacePoints->reserve(sps.size());
237 
238  fillSpacepoints(spacePoints, sps, inputClusters);
239 
240  if(overlapSpacePoints && m_processOverlapForStrip){
241  overlapSpacePoints->reserve(osps.size());
242  fillSpacepoints(overlapSpacePoints, osps, inputClusters);
243  }
244  }
245 
246  nReceivedSPsStrip = stripSpacePointContainer->size();
247 
248  mon_nCachedIdHashes = nCachedIdHashes;
249 
250  if(m_processOverlapForStrip){
251  nReceivedSPsStripOverlap = overlapSpacePoints->size();
252  }else{
253  nReceivedSPsStripOverlap = 0; //avoid undefined value
254  }
255 
256  m_stat[kNSpacePoints] += nReceivedSPsStrip;
257  m_stat[kNOverlapSpacePoints] += nReceivedSPsStripOverlap;
258 
259  return StatusCode::SUCCESS;
260  }
261 
262  template <bool useCache>
263  void StripSpacePointFormationAlgBase<useCache>::fillSpacepoints(xAOD::SpacePointContainer* cont, std::vector<StripSP>& input, const xAOD::StripClusterContainer* inputClusters, unsigned int indexBase) const{
264  std::vector<xAOD::SpacePoint*> sp_collection;
265  sp_collection.reserve(input.size());
266  for (std::size_t i(0); i<input.size(); ++i)
267  sp_collection.push_back(new xAOD::SpacePoint());
268  cont->insert(cont->end(), sp_collection.begin(), sp_collection.end());
269 
270  // fill
271  for (std::size_t i(0); i<input.size(); ++i) {
272  auto& toAdd = input.at(i);
273 
274  // make link to Clusters
275  std::vector< const xAOD::UncalibratedMeasurement* > els(
276  {inputClusters->at(toAdd.measurementIndexes[0]),
277  inputClusters->at(toAdd.measurementIndexes[1])}
278  );
279  cont->at(indexBase+i)->setSpacePoint(toAdd.idHashes,
280  toAdd.globPos,
281  toAdd.cov_r,
282  toAdd.cov_z,
283  els,
284  toAdd.topHalfStripLength,
285  toAdd.bottomHalfStripLength,
286  toAdd.topStripDirection,
287  toAdd.bottomStripDirection,
288  toAdd.stripCenterDistance,
289  toAdd.topStripCenter);
290  }
291  }
292 }