2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
5 #include "InDetReadoutGeometry/SiDetectorElement.h"
6 #include "PixelReadoutGeometry/PixelModuleDesign.h"
8 #include "xAODInDetMeasurement/PixelClusterAuxContainer.h"
10 #include "AthenaMonitoringKernel/Monitored.h"
11 #include "ActsInterop/TableUtils.h"
17 //------------------------------------------------------------------------
18 template <bool useCache>
19 PixelSpacePointFormationAlgBase<useCache>::PixelSpacePointFormationAlgBase(const std::string& name,
20 ISvcLocator* pSvcLocator)
21 : AthReentrantAlgorithm(name, pSvcLocator)
24 //-----------------------------------------------------------------------
25 template <bool useCache>
26 StatusCode PixelSpacePointFormationAlgBase<useCache>::initialize()
28 ATH_MSG_DEBUG( "Initializing " << name() << " ... " );
30 ATH_CHECK( m_pixelClusterContainerKey.initialize() );
31 ATH_CHECK( m_pixelSpacePointContainerKey.initialize() );
32 ATH_CHECK( m_pixelDetEleCollKey.initialize() );
33 ATH_CHECK( m_spacePointMakerTool.retrieve() );
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));
42 return StatusCode::SUCCESS;
45 template <bool useCache>
46 StatusCode PixelSpacePointFormationAlgBase<useCache>::finalize()
48 ATH_MSG_INFO("Space Point Formation statistics" << std::endl << makeTable(m_stat,
49 std::array<std::string, kNStat>{
54 return StatusCode::SUCCESS;
57 //-------------------------------------------------------------------------
58 template <bool useCache>
59 StatusCode PixelSpacePointFormationAlgBase<useCache>::execute (const EventContext& ctx) const
61 auto timer = Monitored::Timer<std::chrono::milliseconds>( "TIME_execute" );
62 auto nReceivedSPsPixel = Monitored::Scalar<int>( "numPixSpacePoints" , 0 );
63 auto mon = Monitored::Group( m_monTool, timer, nReceivedSPsPixel );
65 SG::ReadHandle<xAOD::PixelClusterContainer> inputPixelClusterContainer( m_pixelClusterContainerKey, ctx );
66 if (!inputPixelClusterContainer.isValid()){
67 ATH_MSG_FATAL("xAOD::PixelClusterContainer with key " << m_pixelClusterContainerKey.key() << " is not available...");
68 return StatusCode::FAILURE;
70 const xAOD::PixelClusterContainer *pixelClusters = inputPixelClusterContainer.cptr();
71 ATH_MSG_DEBUG("Retrieved " << pixelClusters->size() << " clusters from container " << m_pixelClusterContainerKey.key());
72 m_stat[kNClusters] += pixelClusters->size();
74 auto pixelSpacePointContainer = SG::WriteHandle<xAOD::SpacePointContainer>( m_pixelSpacePointContainerKey, ctx );
75 ATH_MSG_DEBUG( "--- Pixel Space Point Container `" << m_pixelSpacePointContainerKey.key() << "` created ..." );
76 ATH_CHECK(pixelSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
77 std::make_unique<xAOD::SpacePointAuxContainer>() ));
78 xAOD::SpacePointContainer *pixelSpacePoints = pixelSpacePointContainer.ptr();
80 Cache_WriteHandle cacheHandle;
81 if constexpr (useCache) {
82 cacheHandle = Cache_WriteHandle(m_SPCache, ctx);
83 auto updateHandle = Cache_BackendUpdateHandle(m_SPCacheBackend, ctx);
84 ATH_CHECK(updateHandle.isValid());
85 ATH_CHECK(cacheHandle.record(std::make_unique<Cache_IDC>(updateHandle.ptr())));
86 ATH_CHECK(cacheHandle.isValid());
90 pixelSpacePoints->reserve(pixelClusters->size());
92 // Early exit in case we have no clusters
93 // We still are saving an empty space point container in SG
94 if (pixelClusters->empty()) {
95 ATH_MSG_DEBUG("No input clusters found, we stop space point formation");
96 return StatusCode::SUCCESS;
99 SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> pixelDetEleHandle(m_pixelDetEleCollKey, ctx);
100 const InDetDD::SiDetectorElementCollection* pixelElements(*pixelDetEleHandle);
101 if (not pixelDetEleHandle.isValid() or pixelElements==nullptr) {
102 ATH_MSG_FATAL(m_pixelDetEleCollKey.fullKey() << " is not available.");
103 return StatusCode::FAILURE;
108 // using trick for fast insertion
109 std::vector< xAOD::SpacePoint* > preCollection;
110 preCollection.reserve(pixelClusters->size());
111 for ( std::size_t i(0); i<inputPixelClusterContainer->size(); ++i)
112 preCollection.push_back( new xAOD::SpacePoint() );
113 pixelSpacePoints->insert(pixelSpacePoints->end(), preCollection.begin(), preCollection.end());
116 std::map<IdentifierHash, std::vector<std::pair<unsigned int, unsigned int>>> cache_ranges;
117 int groupStartIdx = 0;
118 std::optional<IdentifierHash> groupIdHash = std::nullopt;
120 //when using the cache some clusters can be skipped, this results in discontinuous spacepoints (but the unpopulated SP still exists and is getting filled into the cache and the output container)
121 //need to track the index of the spacepoints which are being inserted, so they are continuous and so that the output collection can be trimmed
122 unsigned int spIdx = 0;
124 for(unsigned int idx=0; idx<pixelClusters->size(); idx++){
125 const xAOD::PixelCluster* cluster = pixelClusters->at(idx);
126 IdentifierHash idHash = cluster->identifierHash();
127 if constexpr(useCache){
128 //check if the idHash is already in the cache
129 if(cacheHandle->tryAddFromCache(idHash)) continue;
132 const InDetDD::SiDetectorElement* pixelElement = pixelElements->getDetectorElement(idHash);
133 if (pixelElement == nullptr) {
134 ATH_MSG_FATAL("Element pointer is nullptr");
135 return StatusCode::FAILURE;
138 //get the index of the output spacepoint, when not using the cache this should be equal to the cluster index
139 unsigned int thisSpIdx = spIdx++;
141 ATH_CHECK( m_spacePointMakerTool->producePixelSpacePoint(*cluster,
142 *pixelSpacePoints->at(thisSpIdx),
145 if constexpr(useCache){
146 //check if the groupIdHash is defined if so and if it has changed then insert the range into the map
147 if(groupIdHash && ((*groupIdHash) != idHash)){
148 cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, thisSpIdx);
149 groupStartIdx = thisSpIdx;
152 groupIdHash = idHash;
156 //handle final idHash
157 if constexpr(useCache){
159 cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, spIdx);
163 //finally resize the output for the actual number of inserted spacepoints
164 pixelSpacePoints->resize(spIdx);
167 if constexpr(useCache){
168 //add the ranges to the cache
169 for(auto idr: cache_ranges){
170 auto wh = cacheHandle->getWriteHandle(idr.first);
171 //check that item is not in the cache already (again)
172 if(wh.OnlineAndPresentInAnotherView()) continue;
173 auto ce = std::make_unique<Cache::CacheEntry<xAOD::SpacePoint>>(pixelSpacePoints, idr.second);
174 ATH_CHECK(wh.addOrDelete(std::move(ce)));
178 nReceivedSPsPixel = pixelSpacePointContainer->size();
179 m_stat[kNSpacePoints] += nReceivedSPsPixel;
180 return StatusCode::SUCCESS;