ATLAS Offline Software
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 
12 
15 #include "InDetIdentifier/SCT_ID.h"
18 #include "StoreGate/WriteHandle.h"
20 
21 #include "AthAllocators/DataPool.h"
22 #include <limits>
23 #include <unordered_map>
24 
25 namespace 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());
46  ATH_CHECK(m_flaggedCondCacheKey.initialize(not m_flaggedCondCacheKey.key().empty()));
47 
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()) {
58  ATH_CHECK(m_regionSelector.retrieve());
59  } else {
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 
87  ATH_CHECK(clusterContainer.symLink(m_clusterContainerLinkKey));
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};
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};
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 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
SCT_FlaggedCondEnum.h
header file for enum for SCT_Clusterization and SCT_FlaggedConditionTool.
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
SCT_ID.h
This is an Identifier helper class for the SCT subdetector. This class is a factory for creating comp...
TrigDefs::Group
Group
Properties of a chain group.
Definition: GroupProperties.h:13
InDet::SCT_Clusterization::SCT_Clusterization
SCT_Clusterization()=delete
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
InDet::SCT_Clusterization::m_flaggedCondDataKey
SG::WriteHandleKey< IDCInDetBSErrContainer > m_flaggedCondDataKey
Definition: SCT_Clusterization.h:102
InDet::SCT_Clusterization::m_idHelper
const SCT_ID * m_idHelper
Definition: SCT_Clusterization.h:90
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
InDet::SCTClusteringCache::idGroups
std::vector< IdVec_t > idGroups
Definition: ISCT_ClusteringTool.h:36
InDet
Primary Vertex Finder.
Definition: VP1ErrorUtils.h:36
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
SG::UpdateHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
SCT_Clusterization.h
InDet::SCT_Clusterization::m_roiSeeded
BooleanProperty m_roiSeeded
Definition: SCT_Clusterization.h:122
InDet::SCT_Clusterization::m_maxFiredStrips
UnsignedIntegerProperty m_maxFiredStrips
Definition: SCT_Clusterization.h:120
athena.value
value
Definition: athena.py:124
SCT_RDORawData
Definition: SCT_RDORawData.h:24
InDet::SCT_Clusterization::m_sctDetElStatus
SG::ReadHandleKey< InDet::SiDetectorElementStatus > m_sctDetElStatus
Optional read handle to get status data to test whether a SCT detector element is good.
Definition: SCT_Clusterization.h:114
SCT_FlaggedCondEnum::ExceedMaxFiredStrips
@ ExceedMaxFiredStrips
Definition: SCT_FlaggedCondEnum.h:26
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
InDet::SCTClusteringCache::tbinGroups
std::vector< uint16_t > tbinGroups
Definition: ISCT_ClusteringTool.h:37
InDet::SCT_Clusterization::m_clusterContainerCacheKey
SG::UpdateHandleKey< SCT_ClusterContainerCache > m_clusterContainerCacheKey
For HLT cache.
Definition: SCT_Clusterization.h:104
SG::UpdateHandle::ptr
pointer_type ptr()
Dereference the pointer.
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::detStore
const ServiceHandle< StoreGateSvc > & detStore() const
The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:95
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
InDet::SCT_Clusterization::m_checkBadModules
BooleanProperty m_checkBadModules
Definition: SCT_Clusterization.h:123
InDet::SCT_Clusterization::m_clusteringTool
ToolHandle< ISCT_ClusteringTool > m_clusteringTool
Definition: SCT_Clusterization.h:87
InDet::SCT_Clusterization::m_useDataPoolWithCache
Gaudi::Property< bool > m_useDataPoolWithCache
Definition: SCT_Clusterization.h:124
AtlasDetectorID.h
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
WriteHandle.h
Handle class for recording to StoreGate.
InDet::SCT_Clusterization::m_pSummaryTool
ToolHandle< IInDetConditionsTool > m_pSummaryTool
Definition: SCT_Clusterization.h:88
VALIDATE_STATUS_ARRAY
#define VALIDATE_STATUS_ARRAY(use_info, info_val, summary_val)
Definition: SiDetectorElementStatus.h:51
lumiFormat.i
int i
Definition: lumiFormat.py:85
InDet::SCT_Clusterization::m_regionSelector
ToolHandle< IRegSelTool > m_regionSelector
Definition: SCT_Clusterization.h:86
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
InDet::SCTClusteringCache::currentVector
IdVec_t currentVector
Definition: ISCT_ClusteringTool.h:33
InDetRawDataCollection
Definition: InDetRawDataCollection.h:31
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
IdentifiableContainerMT::const_iterator
Definition: IdentifiableContainerMT.h:79
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
SCT_RDORawData.h
InDet::SCT_Clusterization::m_rdoContainerKey
SG::ReadHandleKey< SCT_RDO_Container > m_rdoContainerKey
Definition: SCT_Clusterization.h:99
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
DataPool.h
InDet::SiDetectorElementStatus::isGood
bool isGood(IdentifierHash hash) const
Definition: SiDetectorElementStatus.h:97
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:227
InDet::SCT_Clusterization::m_clusterContainerLinkKey
SG::WriteHandleKey< SiClusterContainer > m_clusterContainerLinkKey
Definition: SCT_Clusterization.h:101
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
SCT_ID::wafer_hash_max
size_type wafer_hash_max(void) const
Definition: SCT_ID.cxx:645
IdentifierHash.h
SG::UpdateHandle
Definition: UpdateHandle.h:94
InDet::SCT_Clusterization::m_roiCollectionKey
SG::ReadHandleKey< TrigRoiDescriptorCollection > m_roiCollectionKey
Definition: SCT_Clusterization.h:98
EventContainers::Mode::OfflineFast
@ OfflineFast
InDet::SCT_Clusterization::m_maxTotalOccupancyPercent
UnsignedIntegerProperty m_maxTotalOccupancyPercent
Definition: SCT_Clusterization.h:121
InDet::SCT_Clusterization::execute
virtual StatusCode execute(const EventContext &ctx) const override
Form clusters and record them in StoreGate by WriteHandle.
Definition: SCT_Clusterization.cxx:72
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
InDet::SCT_Clusterization::m_flaggedCondCacheKey
SG::UpdateHandleKey< IDCInDetBSErrContainer_Cache > m_flaggedCondCacheKey
For HLT cache.
Definition: SCT_Clusterization.h:106
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:109
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
InDet::SCT_Clusterization::finalize
virtual StatusCode finalize() override
Finalize (nothing done actually)
Definition: SCT_Clusterization.cxx:322
InDet::SCTClusteringCache
Definition: ISCT_ClusteringTool.h:29
Monitored::ScopedTimer
Helper class to create a scoped timer.
Definition: MonitoredTimer.h:95
error
Definition: IImpactPoint3dEstimator.h:70
InDet::SCT_Clusterization::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Definition: SCT_Clusterization.h:89
InDet::SCT_Clusterization::m_clusterContainerKey
SG::WriteHandleKey< SCT_ClusterContainer > m_clusterContainerKey
Definition: SCT_Clusterization.h:100
TrigRoiDescriptorCollection.h
Monitored::Timer
A monitored timer.
Definition: MonitoredTimer.h:32
InDet::SCT_Clusterization::initialize
virtual StatusCode initialize() override
Retrieve the tools used and initialize handle keys.
Definition: SCT_Clusterization.cxx:34