ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_Clusterization.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 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 // Anything to dereference the DataHandle will trigger the converter
110 SCT_RDO_Container::const_iterator rdoCollections{rdoContainer->begin()};
111 SCT_RDO_Container::const_iterator rdoCollectionsEnd{rdoContainer->end()};
112 bool dontDoClusterization{false};
113 //new code to remove large numbers of hits (what is large?)
114 if (m_maxTotalOccupancyPercent.value()!=100) {
115 constexpr unsigned int totalNumberOfChannels{6279168};
116 const unsigned int maxAllowableStrips{(totalNumberOfChannels*m_maxTotalOccupancyPercent.value())/100};//integer arithmetic, should be ok
117 unsigned int totalFiredStrips{0};
118 for (; rdoCollections != rdoCollectionsEnd; ++rdoCollections) {
119 for (const SCT_RDORawData* rdo: **rdoCollections) {
120 totalFiredStrips += rdo->getGroupSize();
121 }
122 } //iterator is now at the end
123 //reset the iterator
124 rdoCollections = rdoContainer->begin();
125 if (totalFiredStrips > maxAllowableStrips) {
126 ATH_MSG_WARNING("This event has too many hits in the SCT: " << totalFiredStrips << " > " << maxAllowableStrips);
127 dontDoClusterization = true;
128 }
129 }
131 if (!m_sctDetElStatus.empty()) {
133 ATH_CHECK( sctDetElStatus.isValid() ? StatusCode::SUCCESS : StatusCode::FAILURE);
134 }
135
136 if (not dontDoClusterization) {
137 std::unique_ptr<DataPool<SCT_Cluster>> dataItemsPool = nullptr;
138 const bool hasExternalCache = rdoContainer->hasExternalCache();
139 if (!hasExternalCache) {
140 dataItemsPool = std::make_unique<DataPool<SCT_Cluster>>(ctx);
141 dataItemsPool->reserve(20000); // Some large default size
142 } else if (m_useDataPoolWithCache) {
143 dataItemsPool = std::make_unique<DataPool<SCT_Cluster>>(ctx);
144 // this is per view so let it expand on its own in blocks
145 }
146 // cache to avoid re-allocation inside the loop.
147 // Trying to re-use the vector capacities.
148 // we clear them inside the methods we call
149
150 SCTClusteringCache cache;
151 cache.currentVector.reserve(32);
152 cache.idGroups.reserve(16);
153 cache.tbinGroups.reserve(16);
154 if (not m_roiSeeded.value()) { // Full-scan mode
155
156 for (; rdoCollections != rdoCollectionsEnd; ++rdoCollections) {
157 const InDetRawDataCollection<SCT_RDORawData>* rd{*rdoCollections};
158 ATH_MSG_DEBUG("RDO collection size=" << rd->size() << ", Hash="
159 << rd->identifyHash());
160 SCT_ClusterContainer::IDC_WriteHandle lock{
161 clusterContainer->getWriteHandle(rdoCollections.hashId())};
162 if (lock.OnlineAndPresentInAnotherView()) {
164 "Item already in cache , Hash=" << rd->identifyHash());
165 continue;
166 }
167 bool goodModule{
168 m_checkBadModules.value()
169 ? (!m_sctDetElStatus.empty()
170 ? sctDetElStatus->isGood(rd->identifyHash())
171 : m_pSummaryTool->isGood(rd->identifyHash(), ctx))
172 : true};
174 m_checkBadModules.value() && !m_sctDetElStatus.empty(),
175 sctDetElStatus->isGood(rd->identifyHash()),
176 m_pSummaryTool->isGood(rd->identifyHash(), ctx));
177
178 if (!goodModule) {
179 ATH_MSG_DEBUG(" module status is bad");
180 }
181 // Check the RDO is not empty and that the wafer is good according to
182 // the conditions
183 if ((not rd->empty()) and goodModule) {
184 // If more than a certain number of RDOs set module to bad
185 if (m_maxFiredStrips.value()) {
186 unsigned int nFiredStrips{0};
187 for (const SCT_RDORawData* rdo : *rd) {
188 nFiredStrips += rdo->getGroupSize();
189 }
190 if (nFiredStrips > m_maxFiredStrips.value()) {
191 // This should work in the case of a new code or existing, since
192 // the default init is 0
193 constexpr int value =
195 auto [pPair, inserted] =
196 flaggedCondMap.insert({rd->identifyHash(), value});
197 if (not inserted) {
198 pPair->second |= value;
199 }
200 continue;
201 }
202 }
203 // Use one of the specific clustering AlgTools to make clusters
204 std::unique_ptr<SCT_ClusterCollection> clusterCollection{
205 m_clusteringTool->clusterize(
206 *rd, *m_idHelper,
207 !m_sctDetElStatus.empty() ? sctDetElStatus.cptr() : nullptr,
208 cache, dataItemsPool.get(), ctx)};
209 if (clusterCollection) {
210 if (not clusterCollection->empty()) {
211 const IdentifierHash hash{clusterCollection->identifyHash()};
212 ATH_CHECK(lock.addOrDelete(std::move(clusterCollection)));
213 ATH_MSG_DEBUG("Clusters with key '"
214 << hash << "' added to Container\n");
215 } else {
216 ATH_MSG_DEBUG("Don't write empty collections\n");
217 }
218 } else {
219 ATH_MSG_DEBUG("Clustering algorithm found no clusters\n");
220 }
221 }
222 }
223 } else { // enter RoI-seeded mode
225 m_roiCollectionKey, ctx};
226 ATH_CHECK(roiCollection.isValid());
227 TrigRoiDescriptorCollection::const_iterator roi{roiCollection->begin()};
228 TrigRoiDescriptorCollection::const_iterator roiE{roiCollection->end()};
229 std::vector<IdentifierHash> listOfSCTIds;
230 for (; roi != roiE; ++roi) {
231 listOfSCTIds.clear(); // Prevents needless memory reallocations
232
233 m_regionSelector->lookup(ctx)->HashIDList( **roi, listOfSCTIds );
234
235 ATH_MSG_VERBOSE(**roi);
236 ATH_MSG_VERBOSE("REGTEST: SCT : Roi contains " << listOfSCTIds.size()
237 << " det. Elements");
238 for (size_t i{0}; i < listOfSCTIds.size(); i++) {
239 IdentifierHash id = listOfSCTIds[i];
240 const InDetRawDataCollection<SCT_RDORawData>* RDO_Collection{
241 rdoContainer->indexFindPtr(id)};
242 if (RDO_Collection == nullptr){
243 continue;
244 }
245 bool goodModule;
246 {
247 Monitored::ScopedTimer time_SummaryTool(mnt_timer_SummaryTool);
248 goodModule = {m_checkBadModules.value()
249 ? (!m_sctDetElStatus.empty()
250 ? sctDetElStatus->isGood(id)
251 : m_pSummaryTool->isGood(id, ctx))
252 : true};
254 m_checkBadModules.value() && !m_sctDetElStatus.empty(),
255 sctDetElStatus->isGood(id), m_pSummaryTool->isGood(id));
256 if (!goodModule){
257 ATH_MSG_VERBOSE("module status flagged as BAD");
258 }
259 }
260 // Check the RDO is not empty and that the wafer is good according
261 // to the conditions
262 if ((not RDO_Collection->empty()) and goodModule) {
263 // If more than a certain number of RDOs set module to bad
264 if (m_maxFiredStrips.value()) {
265 unsigned int nFiredStrips{0};
266 for (const SCT_RDORawData* rdo : *RDO_Collection){
267 nFiredStrips += rdo->getGroupSize();
268 }
269 if (nFiredStrips > m_maxFiredStrips.value()) {
270 // This should work in the case of a new code or existing,
271 // since the default init is 0
272 constexpr int value =
274 auto [pPair, inserted] = flaggedCondMap.insert({id, value});
275 if (not inserted) {
276 pPair->second |= value;
277 }
278 continue;
279 }
280 }
281 }
282
283 SCT_ClusterContainer::IDC_WriteHandle lock{
284 clusterContainer->getWriteHandle(listOfSCTIds[i])};
285 if (lock.OnlineAndPresentInAnotherView()) {
286 ATH_MSG_DEBUG("Item already in cache , Hash=" << listOfSCTIds[i]);
287 continue;
288 }
289
290 // Use one of the specific clustering AlgTools to make clusters
291 {
292 Monitored::ScopedTimer time_Clusterize(mnt_timer_Clusterize);
293 std::unique_ptr<SCT_ClusterCollection> clusterCollection{
294 m_clusteringTool->clusterize(
295 *RDO_Collection, *m_idHelper,
296 !m_sctDetElStatus.empty() ? sctDetElStatus.cptr()
297 : nullptr,
298 cache, dataItemsPool.get(), ctx)};
299 if (clusterCollection and (not clusterCollection->empty())) {
300 ATH_MSG_VERBOSE("REGTEST: SCT : clusterCollection contains " << clusterCollection->size() << " clusters");
301 ATH_CHECK(lock.addOrDelete(std::move(clusterCollection)));
302 } else {
303 ATH_MSG_DEBUG("No SCTClusterCollection to write");
304 }
305 }
306 }
307 }
308 }
309 }
310 // Set container to const
311 ATH_CHECK(clusterContainer.setConst());
312
313 // Fill flaggedCondData
314 for (auto [hash, error] : flaggedCondMap) {
315 flaggedCondData->setOrDrop(hash, error);
316 }
317 auto monTime = Monitored::Group(m_monTool, mnt_timer_Total, mnt_timer_Clusterize, mnt_timer_SummaryTool);
318 return StatusCode::SUCCESS;
319 }
320
321 // Finalize method:
323 {
324 return StatusCode::SUCCESS;
325 }
326}
#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