ATLAS Offline Software
Loading...
Searching...
No Matches
StripSpacePointFormationAlgBase.icc
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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
12namespace 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( not m_overrideBeamSpot ) );
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 Amg::Vector3D vertex(m_xVertex, m_yVertex, m_zVertex);
123 if (not m_overrideBeamSpot) {
124 SG::ReadCondHandle<InDet::BeamSpotData> beamSpotHandle { m_beamSpotKey, ctx };
125 const InDet::BeamSpotData* beamSpot = *beamSpotHandle;
126 vertex = beamSpot->beamVtx().position();
127 }
128
129
130 SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> stripDetEleHandle(m_stripDetEleCollKey, ctx);
131 const InDetDD::SiDetectorElementCollection* stripElements(*stripDetEleHandle);
132 if (not stripDetEleHandle.isValid() or stripElements==nullptr) {
133 ATH_MSG_FATAL(m_stripDetEleCollKey.fullKey() << " is not available.");
134 return StatusCode::FAILURE;
135 }
136
137 SG::ReadCondHandle<InDet::SiElementPropertiesTable> stripProperties(m_stripPropertiesKey, ctx);
138 const InDet::SiElementPropertiesTable* properties = stripProperties.retrieve();
139 if (properties==nullptr) {
140 ATH_MSG_FATAL("Pointer of SiElementPropertiesTable (" << m_stripPropertiesKey.fullKey() << ") could not be retrieved");
141 return StatusCode::FAILURE;
142 }
143 timer_ca.start();
144 ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1> clusterAccessor ( *inputClusters, [](const xAOD::StripCluster& cl) { return cl.identifierHash();}, stripElements->size());
145 timer_ca.stop();
146
147 unsigned int nCachedIdHashes = 0;
148
149 if constexpr(useCache){
150 for(auto idHash: clusterAccessor.allIdentifiers()){
151 //obtain a write handle
152 auto cache_wh = cacheHandle->getWriteHandle(idHash);
153 auto overlap_cache_wh = overlapCacheHandle->getWriteHandle(idHash);
154 //check if objects are available in the cache already (function has a sideeffect of including them in this container if they are)
155 bool fill_sp = true;
156 bool fill_osp = true;
157 //check if already available
158 if(cache_wh.OnlineAndPresentInAnotherView()){
159 nCachedIdHashes += 1;
160 fill_sp = false;
161 }
162
163 //avoid calling a cache function if not going to process osp
164 if(m_processOverlapForStrip){
165 fill_osp = !overlap_cache_wh.OnlineAndPresentInAnotherView();
166 }else{
167 fill_osp = false;
168 }
169
170 //check if we have something to do
171 if(!(fill_sp || fill_osp)){
172 continue;
173 }
174
175 unsigned int nsp = 0;
176
177 for(auto rng: clusterAccessor.rangesForIdentifierDirect(idHash)){
178 nsp += (rng.second - rng.first);
179 }
180
181 // Produce space points
182 std::vector<StripSP> sps;
183 std::vector<StripSP> osps;
184 //reserve the total number of clusters in the starting block
185 //at most will get one spacepoint for two clusters
186 sps.reserve(nsp*0.5);
187 osps.reserve(nsp*0.5);
188
189 ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
190 *inputClusters,
191 *properties,
192 *stripElements,
193 vertex,
194 sps,
195 osps,
196 m_processOverlapForStrip,
197 std::vector<IdentifierHash>{idHash},
198 clusterAccessor) );
199
200
201
202 //cannot insert twice so need to check if we already have something
203 if(fill_sp){
204 unsigned int sp_start_idx = spacePoints->size();
205 fillSpacepoints(spacePoints, sps, inputClusters, sp_start_idx);
206
207 //add to cache
208 ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(cache_wh, spacePoints, sp_start_idx, spacePoints->size()));
209 }
210
211 if(overlapSpacePoints && m_processOverlapForStrip && fill_osp){
212 unsigned int osp_start_idx = overlapSpacePoints->size();
213 fillSpacepoints(overlapSpacePoints, osps, inputClusters, osp_start_idx);
214
215 //add to cache
216 ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(overlap_cache_wh, overlapSpacePoints, osp_start_idx, overlapSpacePoints->size()));
217 }
218 }
219 }else{
220 // Produce space points without caching
221 std::vector<StripSP> sps;
222 std::vector<StripSP> osps;
223 sps.reserve(inputStripClusterContainer->size() * 0.5);
224 osps.reserve(inputStripClusterContainer->size() * 0.5);
225
226 ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
227 *inputClusters,
228 *properties,
229 *stripElements,
230 vertex,
231 sps,
232 osps,
233 m_processOverlapForStrip,
234 clusterAccessor.allIdentifiers(),
235 clusterAccessor) );
236
237 // using trick for fast insertion
238 spacePoints->reserve(sps.size());
239
240 fillSpacepoints(spacePoints, sps, inputClusters);
241
242 if(overlapSpacePoints && m_processOverlapForStrip){
243 overlapSpacePoints->reserve(osps.size());
244 fillSpacepoints(overlapSpacePoints, osps, inputClusters);
245 }
246 }
247
248 nReceivedSPsStrip = stripSpacePointContainer->size();
249
250 mon_nCachedIdHashes = nCachedIdHashes;
251
252 if(m_processOverlapForStrip && overlapSpacePoints){
253 nReceivedSPsStripOverlap = overlapSpacePoints->size();
254 }else{
255 nReceivedSPsStripOverlap = 0; //avoid undefined value
256 }
257
258 m_stat[kNSpacePoints] += nReceivedSPsStrip;
259 m_stat[kNOverlapSpacePoints] += nReceivedSPsStripOverlap;
260
261 return StatusCode::SUCCESS;
262 }
263
264 template <bool useCache>
265 void StripSpacePointFormationAlgBase<useCache>::fillSpacepoints(xAOD::SpacePointContainer* cont, std::vector<StripSP>& input, const xAOD::StripClusterContainer* inputClusters, unsigned int indexBase) const{
266 std::vector<xAOD::SpacePoint*> sp_collection;
267 sp_collection.reserve(input.size());
268 for (std::size_t i(0); i<input.size(); ++i)
269 sp_collection.push_back(new xAOD::SpacePoint());
270 cont->insert(cont->end(), sp_collection.begin(), sp_collection.end());
271
272 // fill
273 for (std::size_t i(0); i<input.size(); ++i) {
274 auto& toAdd = input.at(i);
275
276 // make link to Clusters
277 cont->at(indexBase+i)->setSpacePoint(std::move(toAdd.idHashes),
278 toAdd.globPos,
279 toAdd.cov_r,
280 toAdd.cov_z,
281 std::vector< const xAOD::UncalibratedMeasurement* >(
282 {inputClusters->at(toAdd.measurementIndexes[0]),
283 inputClusters->at(toAdd.measurementIndexes[1])}),
284 toAdd.topHalfStripLength,
285 toAdd.bottomHalfStripLength,
286 toAdd.topStripDirection,
287 toAdd.bottomStripDirection,
288 toAdd.stripCenterDistance,
289 toAdd.topStripCenter);
290 }
291 }
292}