ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_Clusterization.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
10
12
20
22#include <limits>
23#include <unordered_map>
24
25namespace InDet {
26 using namespace InDet;
27
28 // Constructor with parameters:
29 SCT_Clusterization::SCT_Clusterization(const std::string& name, ISvcLocator* pSvcLocator) :
30 AthReentrantAlgorithm(name, pSvcLocator)
31 {}
32
33 // Initialize method:
35 // Get the conditions summary service (continue anyway, just check the pointer
36 // later and declare everything to be 'good' if it is nullptr)
37 ATH_CHECK( m_pSummaryTool.retrieve( DisableTool{!m_checkBadModules.value() || (!m_sctDetElStatus.empty() && !VALIDATE_STATUS_ARRAY_ACTIVATED)} ) );
38
40
41 ATH_CHECK(m_rdoContainerKey.initialize());
42 ATH_CHECK(m_clusterContainerKey.initialize());
45 ATH_CHECK(m_flaggedCondDataKey.initialize());
46 ATH_CHECK(m_flaggedCondCacheKey.initialize(not m_flaggedCondCacheKey.key().empty()));
47
48 ATH_CHECK(m_sctDetElStatus.initialize( !m_sctDetElStatus.empty() ));
49
50 // Get the clustering tool
51 ATH_CHECK(m_clusteringTool.retrieve());
52
53 // Get the SCT ID helper
54 ATH_CHECK(detStore()->retrieve(m_idHelper, "SCT_ID"));
55
56 if (m_roiSeeded.value()) {
57 ATH_CHECK(m_roiCollectionKey.initialize());
58 ATH_CHECK(m_regionSelector.retrieve());
59 } else {
60 ATH_CHECK(m_roiCollectionKey.initialize(false));
61 m_regionSelector.disable();
62 }
63
64 if ( !m_monTool.empty() ) {
65 ATH_CHECK(m_monTool.retrieve() );
66 }
67
68 return StatusCode::SUCCESS;
69 }
70
71 // Execute method:
72 StatusCode SCT_Clusterization::execute(const EventContext& ctx) const {
73 //Monitoring Tool Configuration
74 auto mnt_timer_Total = Monitored::Timer<std::chrono::milliseconds>("TIME_Total");
75 auto mnt_timer_SummaryTool = Monitored::Timer<std::chrono::milliseconds>("TIME_SummaryTool");
76 auto mnt_timer_Clusterize = Monitored::Timer<std::chrono::milliseconds>("TIME_Clusterize");
77 // Register the IdentifiableContainer into StoreGate
79 if (m_clusterContainerCacheKey.key().empty()) {
80 ATH_CHECK(clusterContainer.record(std::make_unique<SCT_ClusterContainer>(m_idHelper->wafer_hash_max(), EventContainers::Mode::OfflineFast)));
81 } else {
83 ATH_CHECK(clusterContainer.record(std::make_unique<SCT_ClusterContainer>(clusterContainercache.ptr())));
84 }
85 ATH_MSG_DEBUG("Container '" << clusterContainer.name() << "' initialised");
86
88 ATH_CHECK(clusterContainer.isValid());
89 ATH_MSG_DEBUG("SCT clusters '" << clusterContainer.name() << "' symlinked in StoreGate");
90
92 if (m_flaggedCondCacheKey.key().empty()) {
93 ATH_CHECK(flaggedCondData.record( std::make_unique<IDCInDetBSErrContainer>(m_idHelper->wafer_hash_max(), std::numeric_limits<IDCInDetBSErrContainer::ErrorCode>::min())));
94 ATH_MSG_DEBUG("Created IDCInDetBSErrContainer w/o using external cache");
95 } else {
97 ATH_CHECK(flaggedCondCacheHandle.isValid() );
98 ATH_CHECK(flaggedCondData.record( std::make_unique<IDCInDetBSErrContainer>(flaggedCondCacheHandle.ptr())) );
99 ATH_MSG_DEBUG("Created SCT IDCInDetBSErrContainer using external cache");
100 }
101 std::unordered_map<IdentifierHash, IDCInDetBSErrContainer::ErrorCode> flaggedCondMap; // temporary store of flagged condition error
102
103 // First, we have to retrieve and access the container, not because we want to
104 // use it, but in order to generate the proxies for the collections, if they
105 // are being provided by a container converter.
107 ATH_CHECK(rdoContainer.isValid());
108
109 SCT_RDO_Container::const_iterator rdoCollections{rdoContainer->begin()};
110 SCT_RDO_Container::const_iterator rdoCollectionsEnd{rdoContainer->end()};
111 bool dontDoClusterization{false};
112 //new code to remove large numbers of hits (what is large?)
113 if (m_maxTotalOccupancyPercent.value()!=100) {
114 constexpr unsigned int totalNumberOfChannels{6279168};
115 const unsigned int maxAllowableStrips{(totalNumberOfChannels*m_maxTotalOccupancyPercent.value())/100};//integer arithmetic, should be ok
116 unsigned int totalFiredStrips{0};
117 for (; rdoCollections != rdoCollectionsEnd; ++rdoCollections) {
118 for (const SCT_RDORawData* rdo: **rdoCollections) {
119 totalFiredStrips += rdo->getGroupSize();
120 }
121 } //iterator is now at the end
122 //reset the iterator
123 rdoCollections = rdoContainer->begin();
124 if (totalFiredStrips > maxAllowableStrips) {
125 ATH_MSG_WARNING("This event has too many hits in the SCT: " << totalFiredStrips << " > " << maxAllowableStrips);
126 dontDoClusterization = true;
127 }
128 }
130 if (!m_sctDetElStatus.empty()) {
132 ATH_CHECK( sctDetElStatus.isValid() ? StatusCode::SUCCESS : StatusCode::FAILURE);
133 }
134
135 if (not dontDoClusterization) {
136 std::unique_ptr<DataPool<SCT_Cluster>> dataItemsPool = nullptr;
137 const bool hasExternalCache = rdoContainer->hasExternalCache();
138 if (!hasExternalCache) {
139 dataItemsPool = std::make_unique<DataPool<SCT_Cluster>>(ctx);
140 dataItemsPool->reserve(20000); // Some large default size
141 } else if (m_useDataPoolWithCache) {
142 dataItemsPool = std::make_unique<DataPool<SCT_Cluster>>(ctx);
143 // this is per view so let it expand on its own in blocks
144 }
145 // cache to avoid re-allocation inside the loop.
146 // Trying to re-use the vector capacities.
147 // we clear them inside the methods we call
148
149 SCTClusteringCache cache;
150 cache.currentVector.reserve(32);
151 cache.idGroups.reserve(16);
152 cache.tbinGroups.reserve(16);
153 if (not m_roiSeeded.value()) { // Full-scan mode
154
155 for (; rdoCollections != rdoCollectionsEnd; ++rdoCollections) {
156 const InDetRawDataCollection<SCT_RDORawData>* rd{*rdoCollections};
157 ATH_MSG_DEBUG("RDO collection size=" << rd->size() << ", Hash="
158 << rd->identifyHash());
159 SCT_ClusterContainer::IDC_WriteHandle lock{
160 clusterContainer->getWriteHandle(rdoCollections.hashId())};
161 if (lock.OnlineAndPresentInAnotherView()) {
163 "Item already in cache , Hash=" << rd->identifyHash());
164 continue;
165 }
166 bool goodModule{
167 m_checkBadModules.value()
168 ? (!m_sctDetElStatus.empty()
169 ? sctDetElStatus->isGood(rd->identifyHash())
170 : m_pSummaryTool->isGood(rd->identifyHash(), ctx))
171 : true};
173 m_checkBadModules.value() && !m_sctDetElStatus.empty(),
174 sctDetElStatus->isGood(rd->identifyHash()),
175 m_pSummaryTool->isGood(rd->identifyHash(), ctx));
176
177 if (!goodModule) {
178 ATH_MSG_DEBUG(" module status is bad");
179 }
180 // Check the RDO is not empty and that the wafer is good according to
181 // the conditions
182 if ((not rd->empty()) and goodModule) {
183 // If more than a certain number of RDOs set module to bad
184 if (m_maxFiredStrips.value()) {
185 unsigned int nFiredStrips{0};
186 for (const SCT_RDORawData* rdo : *rd) {
187 nFiredStrips += rdo->getGroupSize();
188 }
189 if (nFiredStrips > m_maxFiredStrips.value()) {
190 // This should work in the case of a new code or existing, since
191 // the default init is 0
192 constexpr int value =
194 auto [pPair, inserted] =
195 flaggedCondMap.insert({rd->identifyHash(), value});
196 if (not inserted) {
197 pPair->second |= value;
198 }
199 continue;
200 }
201 }
202 // Use one of the specific clustering AlgTools to make clusters
203 std::unique_ptr<SCT_ClusterCollection> clusterCollection{
204 m_clusteringTool->clusterize(
205 *rd, *m_idHelper,
206 !m_sctDetElStatus.empty() ? sctDetElStatus.cptr() : nullptr,
207 cache, dataItemsPool.get(), ctx)};
208 if (clusterCollection) {
209 if (not clusterCollection->empty()) {
210 const IdentifierHash hash{clusterCollection->identifyHash()};
211 ATH_CHECK(lock.addOrDelete(std::move(clusterCollection)));
212 ATH_MSG_DEBUG("Clusters with key '"
213 << hash << "' added to Container\n");
214 } else {
215 ATH_MSG_DEBUG("Don't write empty collections\n");
216 }
217 } else {
218 ATH_MSG_DEBUG("Clustering algorithm found no clusters\n");
219 }
220 }
221 }
222 } else { // enter RoI-seeded mode
224 m_roiCollectionKey, ctx};
225 ATH_CHECK(roiCollection.isValid());
226 TrigRoiDescriptorCollection::const_iterator roi{roiCollection->begin()};
227 TrigRoiDescriptorCollection::const_iterator roiE{roiCollection->end()};
228 std::vector<IdentifierHash> listOfSCTIds;
229 for (; roi != roiE; ++roi) {
230 listOfSCTIds.clear(); // Prevents needless memory reallocations
231
232 m_regionSelector->lookup(ctx)->HashIDList( **roi, listOfSCTIds );
233
234 ATH_MSG_VERBOSE(**roi);
235 ATH_MSG_VERBOSE("REGTEST: SCT : Roi contains " << listOfSCTIds.size()
236 << " det. Elements");
237 for (size_t i{0}; i < listOfSCTIds.size(); i++) {
238 IdentifierHash id = listOfSCTIds[i];
239 const InDetRawDataCollection<SCT_RDORawData>* RDO_Collection{
240 rdoContainer->indexFindPtr(id)};
241 if (RDO_Collection == nullptr){
242 continue;
243 }
244 bool goodModule;
245 {
246 Monitored::ScopedTimer time_SummaryTool(mnt_timer_SummaryTool);
247 goodModule = {m_checkBadModules.value()
248 ? (!m_sctDetElStatus.empty()
249 ? sctDetElStatus->isGood(id)
250 : m_pSummaryTool->isGood(id, ctx))
251 : true};
253 m_checkBadModules.value() && !m_sctDetElStatus.empty(),
254 sctDetElStatus->isGood(id), m_pSummaryTool->isGood(id));
255 if (!goodModule){
256 ATH_MSG_VERBOSE("module status flagged as BAD");
257 }
258 }
259 // Check the RDO is not empty and that the wafer is good according
260 // to the conditions
261 if ((not RDO_Collection->empty()) and goodModule) {
262 // If more than a certain number of RDOs set module to bad
263 if (m_maxFiredStrips.value()) {
264 unsigned int nFiredStrips{0};
265 for (const SCT_RDORawData* rdo : *RDO_Collection){
266 nFiredStrips += rdo->getGroupSize();
267 }
268 if (nFiredStrips > m_maxFiredStrips.value()) {
269 // This should work in the case of a new code or existing,
270 // since the default init is 0
271 constexpr int value =
273 auto [pPair, inserted] = flaggedCondMap.insert({id, value});
274 if (not inserted) {
275 pPair->second |= value;
276 }
277 continue;
278 }
279 }
280 }
281
282 SCT_ClusterContainer::IDC_WriteHandle lock{
283 clusterContainer->getWriteHandle(listOfSCTIds[i])};
284 if (lock.OnlineAndPresentInAnotherView()) {
285 ATH_MSG_DEBUG("Item already in cache , Hash=" << listOfSCTIds[i]);
286 continue;
287 }
288
289 // Use one of the specific clustering AlgTools to make clusters
290 {
291 Monitored::ScopedTimer time_Clusterize(mnt_timer_Clusterize);
292 std::unique_ptr<SCT_ClusterCollection> clusterCollection{
293 m_clusteringTool->clusterize(
294 *RDO_Collection, *m_idHelper,
295 !m_sctDetElStatus.empty() ? sctDetElStatus.cptr()
296 : nullptr,
297 cache, dataItemsPool.get(), ctx)};
298 if (clusterCollection and (not clusterCollection->empty())) {
299 ATH_MSG_VERBOSE("REGTEST: SCT : clusterCollection contains " << clusterCollection->size() << " clusters");
300 ATH_CHECK(lock.addOrDelete(std::move(clusterCollection)));
301 } else {
302 ATH_MSG_DEBUG("No SCTClusterCollection to write");
303 }
304 }
305 }
306 }
307 }
308 }
309 // Set container to const
310 ATH_CHECK(clusterContainer.setConst());
311
312 // Fill flaggedCondData
313 for (auto [hash, error] : flaggedCondMap) {
314 flaggedCondData->setOrDrop(hash, error);
315 }
316 auto monTime = Monitored::Group(m_monTool, mnt_timer_Total, mnt_timer_Clusterize, mnt_timer_SummaryTool);
317 return StatusCode::SUCCESS;
318 }
319
320 // Finalize method:
322 {
323 return StatusCode::SUCCESS;
324 }
325}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
header file for enum for SCT_Clusterization and SCT_FlaggedConditionTool.
This is an Identifier helper class for the SCT subdetector.
#define VALIDATE_STATUS_ARRAY(use_info, info_val, summary_val)
Handle class for recording to StoreGate.
const ServiceHandle< StoreGateSvc > & detStore() const
An algorithm that can be simultaneously executed in multiple threads.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
IdentifierHash hashId() const
hashId of the pointed-to element
This is a "hash" representation of an Identifier.
virtual IdentifierHash identifyHash() const override final
ToolHandle< ISCT_ClusteringTool > m_clusteringTool
ToolHandle< GenericMonitoringTool > m_monTool
virtual StatusCode initialize() override
Retrieve the tools used and initialize handle keys.
SG::WriteHandleKey< SiClusterContainer > m_clusterContainerLinkKey
ToolHandle< IInDetConditionsTool > m_pSummaryTool
SG::ReadHandleKey< SCT_RDO_Container > m_rdoContainerKey
SG::UpdateHandleKey< IDCInDetBSErrContainer_Cache > m_flaggedCondCacheKey
For HLT cache.
SG::WriteHandleKey< IDCInDetBSErrContainer > m_flaggedCondDataKey
ToolHandle< IRegSelTool > m_regionSelector
SG::ReadHandleKey< InDet::SiDetectorElementStatus > m_sctDetElStatus
Optional read handle to get status data to test whether a SCT detector element is good.
UnsignedIntegerProperty m_maxTotalOccupancyPercent
virtual StatusCode finalize() override
Finalize (nothing done actually)
virtual StatusCode execute(const EventContext &ctx) const override
Form clusters and record them in StoreGate by WriteHandle.
Gaudi::Property< bool > m_useDataPoolWithCache
SG::WriteHandleKey< SCT_ClusterContainer > m_clusterContainerKey
UnsignedIntegerProperty m_maxFiredStrips
SG::UpdateHandleKey< SCT_ClusterContainerCache > m_clusterContainerCacheKey
For HLT cache.
SG::ReadHandleKey< TrigRoiDescriptorCollection > m_roiCollectionKey
Group of local monitoring quantities and retain correlation when filling histograms
Helper class to create a scoped timer.
A monitored timer.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
pointer_type ptr()
Dereference the pointer.
StatusCode setConst()
Set the 'const' bit for the bound proxy in the store.
const std::string & name() const
Return the StoreGate ID for the referenced object.
StatusCode symLink(const WriteHandleKey< U > &key)
Make an explicit link.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Primary Vertex Finder.
std::vector< IdVec_t > idGroups
std::vector< uint16_t > tbinGroups