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;
106 // insertion of big collections
107 pixelSpacePoints->push_new(pixelClusters->size(), [] () {return new xAOD::SpacePoint();});
109 std::map<IdentifierHash, std::vector<std::pair<unsigned int, unsigned int>>> cache_ranges;
110 int groupStartIdx = 0;
111 std::optional<IdentifierHash> groupIdHash = std::nullopt;
113 //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)
114 //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
115 unsigned int spIdx = 0;
117 for(unsigned int idx=0; idx<pixelClusters->size(); idx++){
118 const xAOD::PixelCluster* cluster = pixelClusters->at(idx);
119 IdentifierHash idHash = cluster->identifierHash();
120 if constexpr(useCache){
121 //check if the idHash is already in the cache
122 if(cacheHandle->tryAddFromCache(idHash)) continue;
125 const InDetDD::SiDetectorElement* pixelElement = pixelElements->getDetectorElement(idHash);
126 if (pixelElement == nullptr) {
127 ATH_MSG_FATAL("Element pointer is nullptr");
128 return StatusCode::FAILURE;
131 //get the index of the output spacepoint, when not using the cache this should be equal to the cluster index
132 unsigned int thisSpIdx = spIdx++;
134 ATH_CHECK( m_spacePointMakerTool->producePixelSpacePoint(*cluster,
135 *pixelSpacePoints->at(thisSpIdx),
138 if constexpr(useCache){
139 //check if the groupIdHash is defined if so and if it has changed then insert the range into the map
140 if(groupIdHash && ((*groupIdHash) != idHash)){
141 cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, thisSpIdx);
142 groupStartIdx = thisSpIdx;
145 groupIdHash = idHash;
149 //handle final idHash
150 if constexpr(useCache){
152 cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, spIdx);
156 //finally resize the output for the actual number of inserted spacepoints
157 pixelSpacePoints->resize(spIdx);
160 if constexpr(useCache){
161 //add the ranges to the cache
162 for(auto idr: cache_ranges){
163 auto wh = cacheHandle->getWriteHandle(idr.first);
164 //check that item is not in the cache already (again)
165 if(wh.OnlineAndPresentInAnotherView()) continue;
166 auto ce = std::make_unique<Cache::CacheEntry<xAOD::SpacePoint>>(pixelSpacePoints, idr.second);
167 ATH_CHECK(wh.addOrDelete(std::move(ce)));
171 nReceivedSPsPixel = pixelSpacePointContainer->size();
172 m_stat[kNSpacePoints] += nReceivedSPsPixel;
173 return StatusCode::SUCCESS;