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"
19 #include "StoreGate/WriteHandle.h"
21 
22 #include "AthAllocators/DataPool.h"
23 #include <limits>
24 #include <unordered_map>
25 
26 namespace InDet {
27  using namespace InDet;
28 
29  // Constructor with parameters:
30  SCT_Clusterization::SCT_Clusterization(const std::string& name, ISvcLocator* pSvcLocator) :
31  AthReentrantAlgorithm(name, pSvcLocator)
32  {
33  // Get parameter values from jobOptions file
34  declareProperty("ClusterContainerCacheKey", m_clusterContainerCacheKey="");
35  declareProperty("FlaggedCondCacheKey", m_flaggedCondCacheKey="");
36  }
37 
38  // Initialize method:
40  // Get the conditions summary service (continue anyway, just check the pointer
41  // later and declare everything to be 'good' if it is nullptr)
42  ATH_CHECK( m_pSummaryTool.retrieve( DisableTool{!m_checkBadModules.value() || (!m_sctDetElStatus.empty() && !VALIDATE_STATUS_ARRAY_ACTIVATED)} ) );
43 
45 
46  ATH_CHECK(m_rdoContainerKey.initialize());
51  ATH_CHECK(m_flaggedCondCacheKey.initialize(not m_flaggedCondCacheKey.key().empty()));
52 
54 
55  // Get the clustering tool
56  ATH_CHECK(m_clusteringTool.retrieve());
57 
58  // Get the SCT ID helper
59  ATH_CHECK(detStore()->retrieve(m_idHelper, "SCT_ID"));
60 
61  if (m_roiSeeded.value()) {
63  ATH_CHECK(m_regionSelector.retrieve());
64  } else {
66  m_regionSelector.disable();
67  }
68 
69  if ( !m_monTool.empty() ) {
70  ATH_CHECK(m_monTool.retrieve() );
71  }
72 
73  return StatusCode::SUCCESS;
74  }
75 
76  // Execute method:
77  StatusCode SCT_Clusterization::execute(const EventContext& ctx) const {
78  //Monitoring Tool Configuration
79  auto mnt_timer_Total = Monitored::Timer<std::chrono::milliseconds>("TIME_Total");
80  auto mnt_timer_SummaryTool = Monitored::Timer<std::chrono::milliseconds>("TIME_SummaryTool");
81  auto mnt_timer_Clusterize = Monitored::Timer<std::chrono::milliseconds>("TIME_Clusterize");
82  // Register the IdentifiableContainer into StoreGate
84  if (m_clusterContainerCacheKey.key().empty()) {
85  ATH_CHECK(clusterContainer.record(std::make_unique<SCT_ClusterContainer>(m_idHelper->wafer_hash_max(), EventContainers::Mode::OfflineFast)));
86  } else {
88  ATH_CHECK(clusterContainer.record(std::make_unique<SCT_ClusterContainer>(clusterContainercache.ptr())));
89  }
90  ATH_MSG_DEBUG("Container '" << clusterContainer.name() << "' initialised");
91 
92  ATH_CHECK(clusterContainer.symLink(m_clusterContainerLinkKey));
93  ATH_CHECK(clusterContainer.isValid());
94  ATH_MSG_DEBUG("SCT clusters '" << clusterContainer.name() << "' symlinked in StoreGate");
95 
97  if (m_flaggedCondCacheKey.key().empty()) {
98  ATH_CHECK(flaggedCondData.record( std::make_unique<IDCInDetBSErrContainer>(m_idHelper->wafer_hash_max(), std::numeric_limits<IDCInDetBSErrContainer::ErrorCode>::min())));
99  ATH_MSG_DEBUG("Created IDCInDetBSErrContainer w/o using external cache");
100  } else {
102  ATH_CHECK(flaggedCondCacheHandle.isValid() );
103  ATH_CHECK(flaggedCondData.record( std::make_unique<IDCInDetBSErrContainer>(flaggedCondCacheHandle.ptr())) );
104  ATH_MSG_DEBUG("Created SCT IDCInDetBSErrContainer using external cache");
105  }
106  std::unordered_map<IdentifierHash, IDCInDetBSErrContainer::ErrorCode> flaggedCondMap; // temporary store of flagged condition error
107 
108  // First, we have to retrieve and access the container, not because we want to
109  // use it, but in order to generate the proxies for the collections, if they
110  // are being provided by a container converter.
112  ATH_CHECK(rdoContainer.isValid());
113 
114  // Anything to dereference the DataHandle will trigger the converter
115  SCT_RDO_Container::const_iterator rdoCollections{rdoContainer->begin()};
116  SCT_RDO_Container::const_iterator rdoCollectionsEnd{rdoContainer->end()};
117  bool dontDoClusterization{false};
118  //new code to remove large numbers of hits (what is large?)
119  if (m_maxTotalOccupancyPercent.value()!=100) {
120  constexpr unsigned int totalNumberOfChannels{6279168};
121  const unsigned int maxAllowableStrips{(totalNumberOfChannels*m_maxTotalOccupancyPercent.value())/100};//integer arithmetic, should be ok
122  unsigned int totalFiredStrips{0};
123  for (; rdoCollections != rdoCollectionsEnd; ++rdoCollections) {
124  for (const SCT_RDORawData* rdo: **rdoCollections) {
125  totalFiredStrips += rdo->getGroupSize();
126  }
127  } //iterator is now at the end
128  //reset the iterator
129  rdoCollections = rdoContainer->begin();
130  if (totalFiredStrips > maxAllowableStrips) {
131  ATH_MSG_WARNING("This event has too many hits in the SCT: " << totalFiredStrips << " > " << maxAllowableStrips);
132  dontDoClusterization = true;
133  }
134  }
136  if (!m_sctDetElStatus.empty()) {
138  ATH_CHECK( sctDetElStatus.isValid() ? StatusCode::SUCCESS : StatusCode::FAILURE);
139  }
140 
141  if (not dontDoClusterization) {
142  std::unique_ptr<DataPool<SCT_Cluster>> dataItemsPool = nullptr;
143  const bool hasExternalCache = rdoContainer->hasExternalCache();
144  if (!hasExternalCache) {
145  dataItemsPool = std::make_unique<DataPool<SCT_Cluster>>(ctx);
146  dataItemsPool->reserve(20000); // Some large default size
147  } else if (m_useDataPoolWithCache) {
148  dataItemsPool = std::make_unique<DataPool<SCT_Cluster>>(ctx);
149  // this is per view so let it expand on its own in blocks
150  }
151  // cache to avoid re-allocation inside the loop.
152  // Trying to re-use the vector capacities.
153  // we clear them inside the methods we call
154 
155  SCTClusteringCache cache;
156  cache.currentVector.reserve(32);
157  cache.idGroups.reserve(16);
158  cache.tbinGroups.reserve(16);
159  if (not m_roiSeeded.value()) { // Full-scan mode
160 
161  for (; rdoCollections != rdoCollectionsEnd; ++rdoCollections) {
162  const InDetRawDataCollection<SCT_RDORawData>* rd{*rdoCollections};
163  ATH_MSG_DEBUG("RDO collection size=" << rd->size() << ", Hash="
164  << rd->identifyHash());
165  SCT_ClusterContainer::IDC_WriteHandle lock{
166  clusterContainer->getWriteHandle(rdoCollections.hashId())};
167  if (lock.OnlineAndPresentInAnotherView()) {
169  "Item already in cache , Hash=" << rd->identifyHash());
170  continue;
171  }
172  bool goodModule{
173  m_checkBadModules.value()
174  ? (!m_sctDetElStatus.empty()
175  ? sctDetElStatus->isGood(rd->identifyHash())
176  : m_pSummaryTool->isGood(rd->identifyHash(), ctx))
177  : true};
180  sctDetElStatus->isGood(rd->identifyHash()),
181  m_pSummaryTool->isGood(rd->identifyHash(), ctx));
182 
183  if (!goodModule) {
184  ATH_MSG_DEBUG(" module status is bad");
185  }
186  // Check the RDO is not empty and that the wafer is good according to
187  // the conditions
188  if ((not rd->empty()) and goodModule) {
189  // If more than a certain number of RDOs set module to bad
190  if (m_maxFiredStrips.value()) {
191  unsigned int nFiredStrips{0};
192  for (const SCT_RDORawData* rdo : *rd) {
193  nFiredStrips += rdo->getGroupSize();
194  }
195  if (nFiredStrips > m_maxFiredStrips.value()) {
196  // This should work in the case of a new code or existing, since
197  // the default init is 0
198  constexpr int value =
200  auto [pPair, inserted] =
201  flaggedCondMap.insert({rd->identifyHash(), value});
202  if (not inserted) {
203  pPair->second |= value;
204  }
205  continue;
206  }
207  }
208  // Use one of the specific clustering AlgTools to make clusters
209  std::unique_ptr<SCT_ClusterCollection> clusterCollection{
210  m_clusteringTool->clusterize(
211  *rd, *m_idHelper,
212  !m_sctDetElStatus.empty() ? sctDetElStatus.cptr() : nullptr,
213  cache, dataItemsPool.get(), ctx)};
214  if (clusterCollection) {
215  if (not clusterCollection->empty()) {
216  const IdentifierHash hash{clusterCollection->identifyHash()};
217  ATH_CHECK(lock.addOrDelete(std::move(clusterCollection)));
218  ATH_MSG_DEBUG("Clusters with key '"
219  << hash << "' added to Container\n");
220  } else {
221  ATH_MSG_DEBUG("Don't write empty collections\n");
222  }
223  } else {
224  ATH_MSG_DEBUG("Clustering algorithm found no clusters\n");
225  }
226  }
227  }
228  } else { // enter RoI-seeded mode
230  m_roiCollectionKey, ctx};
231  ATH_CHECK(roiCollection.isValid());
232  TrigRoiDescriptorCollection::const_iterator roi{roiCollection->begin()};
233  TrigRoiDescriptorCollection::const_iterator roiE{roiCollection->end()};
234  std::vector<IdentifierHash> listOfSCTIds;
235  for (; roi != roiE; ++roi) {
236  listOfSCTIds.clear(); // Prevents needless memory reallocations
237  m_regionSelector->HashIDList(**roi, listOfSCTIds);
238  ATH_MSG_VERBOSE(**roi);
239  ATH_MSG_VERBOSE("REGTEST: SCT : Roi contains " << listOfSCTIds.size()
240  << " det. Elements");
241  for (size_t i{0}; i < listOfSCTIds.size(); i++) {
242  IdentifierHash id = listOfSCTIds[i];
243  const InDetRawDataCollection<SCT_RDORawData>* RDO_Collection{
244  rdoContainer->indexFindPtr(id)};
245  if (RDO_Collection == nullptr){
246  continue;
247  }
248  bool goodModule;
249  {
250  Monitored::ScopedTimer time_SummaryTool(mnt_timer_SummaryTool);
251  goodModule = {m_checkBadModules.value()
252  ? (!m_sctDetElStatus.empty()
253  ? sctDetElStatus->isGood(id)
254  : m_pSummaryTool->isGood(id, ctx))
255  : true};
258  sctDetElStatus->isGood(id), m_pSummaryTool->isGood(id));
259  if (!goodModule){
260  ATH_MSG_VERBOSE("module status flagged as BAD");
261  }
262  }
263  // Check the RDO is not empty and that the wafer is good according
264  // to the conditions
265  if ((not RDO_Collection->empty()) and goodModule) {
266  // If more than a certain number of RDOs set module to bad
267  if (m_maxFiredStrips.value()) {
268  unsigned int nFiredStrips{0};
269  for (const SCT_RDORawData* rdo : *RDO_Collection){
270  nFiredStrips += rdo->getGroupSize();
271  }
272  if (nFiredStrips > m_maxFiredStrips.value()) {
273  // This should work in the case of a new code or existing,
274  // since the default init is 0
275  constexpr int value =
277  auto [pPair, inserted] = flaggedCondMap.insert({id, value});
278  if (not inserted) {
279  pPair->second |= value;
280  }
281  continue;
282  }
283  }
284  }
285 
286  SCT_ClusterContainer::IDC_WriteHandle lock{
287  clusterContainer->getWriteHandle(listOfSCTIds[i])};
288  if (lock.OnlineAndPresentInAnotherView()) {
289  ATH_MSG_DEBUG("Item already in cache , Hash=" << listOfSCTIds[i]);
290  continue;
291  }
292 
293  // Use one of the specific clustering AlgTools to make clusters
294  {
295  Monitored::ScopedTimer time_Clusterize(mnt_timer_Clusterize);
296  std::unique_ptr<SCT_ClusterCollection> clusterCollection{
297  m_clusteringTool->clusterize(
298  *RDO_Collection, *m_idHelper,
299  !m_sctDetElStatus.empty() ? sctDetElStatus.cptr()
300  : nullptr,
301  cache, dataItemsPool.get(), ctx)};
302  if (clusterCollection and (not clusterCollection->empty())) {
303  ATH_MSG_VERBOSE("REGTEST: SCT : clusterCollection contains " << clusterCollection->size() << " clusters");
304  ATH_CHECK(lock.addOrDelete(std::move(clusterCollection)));
305  } else {
306  ATH_MSG_DEBUG("No SCTClusterCollection to write");
307  }
308  }
309  }
310  }
311  }
312  }
313  // Set container to const
314  ATH_CHECK(clusterContainer.setConst());
315 
316  // Fill flaggedCondData
317  for (auto [hash, error] : flaggedCondMap) {
318  flaggedCondData->setOrDrop(hash, error);
319  }
320  auto monTime = Monitored::Group(m_monTool, mnt_timer_Total, mnt_timer_Clusterize, mnt_timer_SummaryTool);
321  return StatusCode::SUCCESS;
322  }
323 
324  // Finalize method:
326  {
327  return StatusCode::SUCCESS;
328  }
329 }
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
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
InDet
DUMMY Primary Vertex Finder.
Definition: VP1ErrorUtils.h:36
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:119
InDet::SCT_Clusterization::m_maxFiredStrips
UnsignedIntegerProperty m_maxFiredStrips
Definition: SCT_Clusterization.h:117
athena.value
value
Definition: athena.py:122
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:111
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:103
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:120
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:121
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:92
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:82
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
min
#define min(a, b)
Definition: cfImp.cxx:40
InDet::SiDetectorElementStatus::isGood
bool isGood(IdentifierHash hash) const
Definition: SiDetectorElementStatus.h:97
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:194
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:195
SCT_ID::wafer_hash_max
size_type wafer_hash_max(void) const
Definition: SCT_ID.cxx:639
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:118
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:77
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:104
SiClusterContainer.h
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:325
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:39