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 objects are available in the cache already (function has a sideeffect of including them in this container if they are)
154 bool fill_osp = true;
155 //check if already available
156 if(cache_wh.OnlineAndPresentInAnotherView()){
157 nCachedIdHashes += 1;
161 //avoid calling a cache function if not going to process osp
162 if(m_processOverlapForStrip){
163 fill_osp = !overlap_cache_wh.OnlineAndPresentInAnotherView();
168 //check if we have something to do
169 if(!(fill_sp || fill_osp)){
173 unsigned int nsp = 0;
175 for(auto rng: clusterAccessor.rangesForIdentifierDirect(idHash)){
176 nsp += (rng.second - rng.first);
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);
187 ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
194 m_processOverlapForStrip,
195 std::vector<IdentifierHash>{idHash},
200 //cannot insert twice so need to check if we already have something
202 unsigned int sp_start_idx = spacePoints->size();
203 fillSpacepoints(spacePoints, sps, inputClusters, sp_start_idx);
206 ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(cache_wh, spacePoints, sp_start_idx, spacePoints->size()));
209 if(overlapSpacePoints && m_processOverlapForStrip && fill_osp){
210 unsigned int osp_start_idx = overlapSpacePoints->size();
211 fillSpacepoints(overlapSpacePoints, osps, inputClusters, osp_start_idx);
214 ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(overlap_cache_wh, overlapSpacePoints, osp_start_idx, overlapSpacePoints->size()));
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);
224 ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
231 m_processOverlapForStrip,
232 clusterAccessor.allIdentifiers(),
235 // using trick for fast insertion
236 spacePoints->reserve(sps.size());
238 fillSpacepoints(spacePoints, sps, inputClusters);
240 if(overlapSpacePoints && m_processOverlapForStrip){
241 overlapSpacePoints->reserve(osps.size());
242 fillSpacepoints(overlapSpacePoints, osps, inputClusters);
246 nReceivedSPsStrip = stripSpacePointContainer->size();
248 mon_nCachedIdHashes = nCachedIdHashes;
250 if(m_processOverlapForStrip){
251 nReceivedSPsStripOverlap = overlapSpacePoints->size();
253 nReceivedSPsStripOverlap = 0; //avoid undefined value
256 m_stat[kNSpacePoints] += nReceivedSPsStrip;
257 m_stat[kNOverlapSpacePoints] += nReceivedSPsStripOverlap;
259 return StatusCode::SUCCESS;
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());
271 for (std::size_t i(0); i<input.size(); ++i) {
272 auto& toAdd = input.at(i);
274 // make link to Clusters
275 std::vector< const xAOD::UncalibratedMeasurement* > els(
276 {inputClusters->at(toAdd.measurementIndexes[0]),
277 inputClusters->at(toAdd.measurementIndexes[1])}
279 cont->at(indexBase+i)->setSpacePoint(toAdd.idHashes,
284 toAdd.topHalfStripLength,
285 toAdd.bottomHalfStripLength,
286 toAdd.topStripDirection,
287 toAdd.bottomStripDirection,
288 toAdd.stripCenterDistance,
289 toAdd.topStripCenter);