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 m_useGeometryContext = m_spacePointMakerTool->usesGeometryContext();
36 ATH_CHECK( m_ctxProvider.initialize(m_useGeometryContext) );
38 if ( not m_monTool.empty() )
39 ATH_CHECK( m_monTool.retrieve() );
42 ATH_CHECK(m_SPCache.initialize(useCache));
43 ATH_CHECK(m_SPCacheBackend.initialize(useCache));
45 return StatusCode::SUCCESS;
48 template <bool useCache>
49 StatusCode PixelSpacePointFormationAlgBase<useCache>::finalize()
51 ATH_MSG_INFO("Space Point Formation statistics" << std::endl << makeTable(m_stat,
52 std::array<std::string, kNStat>{
57 return StatusCode::SUCCESS;
60 //-------------------------------------------------------------------------
61 template <bool useCache>
62 StatusCode PixelSpacePointFormationAlgBase<useCache>::execute (const EventContext& ctx) const
64 auto timer = Monitored::Timer<std::chrono::milliseconds>( "TIME_execute" );
65 auto nReceivedSPsPixel = Monitored::Scalar<int>( "numPixSpacePoints" , 0 );
66 auto mon = Monitored::Group( m_monTool, timer, nReceivedSPsPixel );
68 SG::ReadHandle<xAOD::PixelClusterContainer> inputPixelClusterContainer( m_pixelClusterContainerKey, ctx );
69 if (!inputPixelClusterContainer.isValid()){
70 ATH_MSG_FATAL("xAOD::PixelClusterContainer with key " << m_pixelClusterContainerKey.key() << " is not available...");
71 return StatusCode::FAILURE;
73 const xAOD::PixelClusterContainer *pixelClusters = inputPixelClusterContainer.cptr();
74 ATH_MSG_DEBUG("Retrieved " << pixelClusters->size() << " clusters from container " << m_pixelClusterContainerKey.key());
75 m_stat[kNClusters] += pixelClusters->size();
77 auto pixelSpacePointContainer = SG::WriteHandle<xAOD::SpacePointContainer>( m_pixelSpacePointContainerKey, ctx );
78 ATH_MSG_DEBUG( "--- Pixel Space Point Container `" << m_pixelSpacePointContainerKey.key() << "` created ..." );
79 ATH_CHECK(pixelSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
80 std::make_unique<xAOD::SpacePointAuxContainer>() ));
81 xAOD::SpacePointContainer *pixelSpacePoints = pixelSpacePointContainer.ptr();
83 Cache_WriteHandle cacheHandle;
84 if constexpr (useCache) {
85 cacheHandle = Cache_WriteHandle(m_SPCache, ctx);
86 auto updateHandle = Cache_BackendUpdateHandle(m_SPCacheBackend, ctx);
87 ATH_CHECK(updateHandle.isValid());
88 ATH_CHECK(cacheHandle.record(std::make_unique<Cache_IDC>(updateHandle.ptr())));
89 ATH_CHECK(cacheHandle.isValid());
93 pixelSpacePoints->reserve(pixelClusters->size());
95 // Early exit in case we have no clusters
96 // We still are saving an empty space point container in SG
97 if (pixelClusters->empty()) {
98 ATH_MSG_DEBUG("No input clusters found, we stop space point formation");
99 return StatusCode::SUCCESS;
102 SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> pixelDetEleHandle(m_pixelDetEleCollKey, ctx);
103 const InDetDD::SiDetectorElementCollection* pixelElements(*pixelDetEleHandle);
104 if (not pixelDetEleHandle.isValid() or pixelElements==nullptr) {
105 ATH_MSG_FATAL(m_pixelDetEleCollKey.fullKey() << " is not available.");
106 return StatusCode::FAILURE;
109 // insertion of big collections
110 pixelSpacePoints->push_new(pixelClusters->size(), [] () {return new xAOD::SpacePoint();});
112 std::map<IdentifierHash, std::vector<std::pair<unsigned int, unsigned int>>> cache_ranges;
113 int groupStartIdx = 0;
114 std::optional<IdentifierHash> groupIdHash = std::nullopt;
116 //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)
117 //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
118 unsigned int spIdx = 0;
120 Acts::GeometryContext gctx = Acts::GeometryContext::dangerouslyDefaultConstruct();
121 if (m_useGeometryContext) gctx = m_ctxProvider.getGeometryContext(ctx);
123 for(unsigned int idx=0; idx<pixelClusters->size(); idx++){
124 const xAOD::PixelCluster* cluster = pixelClusters->at(idx);
125 IdentifierHash idHash = cluster->identifierHash();
126 if constexpr(useCache){
127 //check if the idHash is already in the cache
128 if(cacheHandle->tryAddFromCache(idHash)) continue;
131 const InDetDD::SiDetectorElement* pixelElement = pixelElements->getDetectorElement(idHash);
132 if (pixelElement == nullptr) {
133 ATH_MSG_FATAL("Element pointer is nullptr");
134 return StatusCode::FAILURE;
137 //get the index of the output spacepoint, when not using the cache this should be equal to the cluster index
138 unsigned int thisSpIdx = spIdx++;
140 ATH_CHECK( m_spacePointMakerTool->producePixelSpacePoint(ctx,
143 *pixelSpacePoints->at(thisSpIdx),
146 if constexpr(useCache){
147 //check if the groupIdHash is defined if so and if it has changed then insert the range into the map
148 if(groupIdHash && ((*groupIdHash) != idHash)){
149 cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, thisSpIdx);
150 groupStartIdx = thisSpIdx;
153 groupIdHash = idHash;
157 //handle final idHash
158 if constexpr(useCache){
160 cache_ranges[(*groupIdHash)].emplace_back(groupStartIdx, spIdx);
164 //finally resize the output for the actual number of inserted spacepoints
165 pixelSpacePoints->resize(spIdx);
168 if constexpr(useCache){
169 //add the ranges to the cache
170 for(auto idr: cache_ranges){
171 auto wh = cacheHandle->getWriteHandle(idr.first);
172 //check that item is not in the cache already (again)
173 if(wh.OnlineAndPresentInAnotherView()) continue;
174 auto ce = std::make_unique<Cache::CacheEntry<xAOD::SpacePoint>>(pixelSpacePoints, idr.second);
175 ATH_CHECK(wh.addOrDelete(std::move(ce)));
179 nReceivedSPsPixel = pixelSpacePointContainer->size();
180 m_stat[kNSpacePoints] += nReceivedSPsPixel;
181 return StatusCode::SUCCESS;