2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
5#include "InDetReadoutGeometry/SiDetectorElement.h"
7#include "xAODInDetMeasurement/StripClusterAuxContainer.h"
9#include "AthenaMonitoringKernel/Monitored.h"
10#include "xAODInDetMeasurement/ContainerAccessor.h"
14 //------------------------------------------------------------------------
15 template <bool useCache>
16 StripSpacePointFormationAlgBase<useCache>::StripSpacePointFormationAlgBase(const std::string& name,
17 ISvcLocator* pSvcLocator)
18 : AthReentrantAlgorithm(name, pSvcLocator)
21 //-----------------------------------------------------------------------
22 template <bool useCache>
23 StatusCode StripSpacePointFormationAlgBase<useCache>::initialize()
25 ATH_MSG_DEBUG( "Initializing " << name() << " ... " );
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() );
33 ATH_CHECK( m_beamSpotKey.initialize( not m_overrideBeamSpot ) );
35 if ( not m_monTool.empty() )
36 ATH_CHECK( m_monTool.retrieve() );
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));
44 return StatusCode::SUCCESS;
47 template <bool useCache>
48 StatusCode StripSpacePointFormationAlgBase<useCache>::finalize()
50 ATH_MSG_INFO("Space Point Formation statistics" << std::endl << makeTable(m_stat,
51 std::array<std::string, kNStat>{
54 "Overlap Space Points"
57 return StatusCode::SUCCESS;
60 //-------------------------------------------------------------------------
61 template <bool useCache>
62 StatusCode StripSpacePointFormationAlgBase<useCache>::execute (const EventContext& ctx) const
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 );
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;
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();
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();
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();
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());
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());
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;
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();
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;
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;
144 ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1> clusterAccessor ( *inputClusters, [](const xAOD::StripCluster& cl) { return cl.identifierHash();}, stripElements->size());
147 unsigned int nCachedIdHashes = 0;
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)
156 bool fill_osp = true;
157 //check if already available
158 if(cache_wh.OnlineAndPresentInAnotherView()){
159 nCachedIdHashes += 1;
163 //avoid calling a cache function if not going to process osp
164 if(m_processOverlapForStrip){
165 fill_osp = !overlap_cache_wh.OnlineAndPresentInAnotherView();
170 //check if we have something to do
171 if(!(fill_sp || fill_osp)){
175 unsigned int nsp = 0;
177 for(auto rng: clusterAccessor.rangesForIdentifierDirect(idHash)){
178 nsp += (rng.second - rng.first);
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);
189 ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
196 m_processOverlapForStrip,
197 std::vector<IdentifierHash>{idHash},
202 //cannot insert twice so need to check if we already have something
204 unsigned int sp_start_idx = spacePoints->size();
205 fillSpacepoints(spacePoints, sps, inputClusters, sp_start_idx);
208 ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(cache_wh, spacePoints, sp_start_idx, spacePoints->size()));
211 if(overlapSpacePoints && m_processOverlapForStrip && fill_osp){
212 unsigned int osp_start_idx = overlapSpacePoints->size();
213 fillSpacepoints(overlapSpacePoints, osps, inputClusters, osp_start_idx);
216 ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(overlap_cache_wh, overlapSpacePoints, osp_start_idx, overlapSpacePoints->size()));
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);
226 ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
233 m_processOverlapForStrip,
234 clusterAccessor.allIdentifiers(),
237 // using trick for fast insertion
238 spacePoints->reserve(sps.size());
240 fillSpacepoints(spacePoints, sps, inputClusters);
242 if(overlapSpacePoints && m_processOverlapForStrip){
243 overlapSpacePoints->reserve(osps.size());
244 fillSpacepoints(overlapSpacePoints, osps, inputClusters);
248 nReceivedSPsStrip = stripSpacePointContainer->size();
250 mon_nCachedIdHashes = nCachedIdHashes;
252 if(m_processOverlapForStrip && overlapSpacePoints){
253 nReceivedSPsStripOverlap = overlapSpacePoints->size();
255 nReceivedSPsStripOverlap = 0; //avoid undefined value
258 m_stat[kNSpacePoints] += nReceivedSPsStrip;
259 m_stat[kNOverlapSpacePoints] += nReceivedSPsStripOverlap;
261 return StatusCode::SUCCESS;
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());
273 for (std::size_t i(0); i<input.size(); ++i) {
274 auto& toAdd = input.at(i);
276 // make link to Clusters
277 cont->at(indexBase+i)->setSpacePoint(std::move(toAdd.idHashes),
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);