2 Copyright (C) 2002-2024 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() );
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 SG::ReadCondHandle<InDet::BeamSpotData> beamSpotHandle { m_beamSpotKey, ctx };
123 const InDet::BeamSpotData* beamSpot = *beamSpotHandle;
124 auto vertex = beamSpot->beamVtx().position();
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;
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;
142 ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1> clusterAccessor ( *inputClusters, [](const xAOD::StripCluster& cl) { return cl.identifierHash();}, stripElements->size());
145 unsigned int nCachedIdHashes = 0;
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;
158 unsigned int nsp = 0;
160 for(auto rng: clusterAccessor.rangesForIdentifierDirect(idHash)){
161 nsp += (rng.second - rng.first);
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
172 ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
179 m_processOverlapForStrip,
180 std::vector<IdentifierHash>{idHash},
183 unsigned int sp_start_idx = spacePoints->size();
185 fillSpacepoints(spacePoints, sps, inputClusters, sp_start_idx);
188 ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(cache_wh, spacePoints, sp_start_idx, spacePoints->size()));
190 if(overlapSpacePoints && m_processOverlapForStrip){
191 unsigned int osp_start_idx = overlapSpacePoints->size();
192 fillSpacepoints(overlapSpacePoints, osps, inputClusters, osp_start_idx);
195 ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(overlap_cache_wh, overlapSpacePoints, osp_start_idx, overlapSpacePoints->size()));
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);
205 ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
212 m_processOverlapForStrip,
213 clusterAccessor.allIdentifiers(),
216 // using trick for fast insertion
217 spacePoints->reserve(sps.size());
219 fillSpacepoints(spacePoints, sps, inputClusters);
221 if(overlapSpacePoints && m_processOverlapForStrip){
222 overlapSpacePoints->reserve(osps.size());
223 fillSpacepoints(overlapSpacePoints, osps, inputClusters);
227 nReceivedSPsStrip = stripSpacePointContainer->size();
229 mon_nCachedIdHashes = nCachedIdHashes;
231 if(m_processOverlapForStrip){
232 nReceivedSPsStripOverlap = overlapSpacePoints->size();
234 nReceivedSPsStripOverlap = 0; //avoid undefined value
237 m_stat[kNSpacePoints] += nReceivedSPsStrip;
238 m_stat[kNOverlapSpacePoints] += nReceivedSPsStripOverlap;
240 return StatusCode::SUCCESS;
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());
252 for (std::size_t i(0); i<input.size(); ++i) {
253 auto& toAdd = input.at(i);
255 // make link to Clusters
256 std::vector< const xAOD::UncalibratedMeasurement* > els(
257 {inputClusters->at(toAdd.measurementIndexes[0]),
258 inputClusters->at(toAdd.measurementIndexes[1])}
260 cont->at(indexBase+i)->setSpacePoint(toAdd.idHashes,
265 toAdd.topHalfStripLength,
266 toAdd.bottomHalfStripLength,
267 toAdd.topStripDirection,
268 toAdd.bottomStripDirection,
269 toAdd.stripCenterDistance,
270 toAdd.topStripCenter);