2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
5#include "Identifier/Identifier.h"
6#include "AtlasDetDescr/AtlasDetectorID.h"
7#include "EventContainers/IdentifiableContainerBase.h"
8#include "InDetRawData/InDetRawDataCollection.h"
9#include "InDetRawData/SCT3_RawData.h"
10#include "InDetRawData/Pixel1RawData.h"
11#include "InDetReadoutGeometry/SiDetectorElement.h"
13#include "AthenaKernel/RNGWrapper.h"
14#include "CLHEP/Random/RandPoisson.h"
15#include "CLHEP/Random/RandFlat.h"
17#include "StoreGate/WriteHandle.h"
26 template <class T_RDO_Container>
27 bool DefectsEmulatorAlg<T_RDO_Container>::setModuleData(const ActsDetectorElement &acts_detector_element,
28 ModuleIdentifierMatchUtil::ModuleData_t &module_data) const {
29 // It is assumed that a module is unambiguously identified by the detector type and the id hash,
30 // and all modules with the same detector type are relevant for the given RDO container.
31 if (acts_detector_element.detectorType() == DETECTOR_TYPE) {
32 const auto*si_detector_element = dynamic_cast<const InDetDD::SiDetectorElement*>(acts_detector_element.upstreamDetectorElement());
33 if(si_detector_element != nullptr) {
34 const T_ModuleDesign &moduleDesign = dynamic_cast<const T_ModuleDesign &>(si_detector_element->design());
35 ModuleIdentifierMatchUtil::setModuleData(*m_idHelper,
36 acts_detector_element.identify(),
45 template <class T_RDO_Container>
46 StatusCode DefectsEmulatorAlg<T_RDO_Container>::initialize(){
47 ATH_CHECK( m_emulatedDefects.initialize() );
48 ATH_CHECK( m_rdoOutContainerKey.initialize() );
49 ATH_CHECK( m_origRdoContainerKey.initialize() );
50 ATH_CHECK( detStore()->retrieve(m_idHelper, m_idHelperName.value()) );
52 return DefectsEmulatorBase::initializeBase(m_idHelper->wafer_hash_max());
55 template <class T_RDO_Container>
56 StatusCode DefectsEmulatorAlg<T_RDO_Container>::execute(const EventContext& ctx) const {
57 SG::ReadCondHandle<T_DefectsData> emulatedDefects(m_emulatedDefects,ctx);
58 ATH_CHECK(emulatedDefects.isValid());
59 SG::ReadHandle<T_RDO_Container> origRdoContainer(m_origRdoContainerKey, ctx);
60 ATH_CHECK(origRdoContainer.isValid());
61 SG::WriteHandle<T_RDO_Container> rdoOutContainer(m_rdoOutContainerKey, ctx);
62 ATH_CHECK( rdoOutContainer.record (std::make_unique<T_RDO_Container>(origRdoContainer->size(), EventContainers::Mode::OfflineFast)) );
64 CLHEP::HepRandomEngine *rndmEngine{};
65 if (!m_noiseProbability.value().empty()){
66 m_rndmSvc->getEngine(this, m_rngName);
67 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_rngName);
68 rngWrapper->setSeed( m_rngName, ctx );
69 rndmEngine = rngWrapper->getEngine(ctx);
72 unsigned int n_rejected=0u;
73 unsigned int n_split_rdos=0u;
75 T_ID_Adapter id_helper(m_idHelper);
76 unsigned int n_added_noise_hits=0u;
77 unsigned int n_defect_noise_hits=0u;
79 std::vector<typename T_ModuleHelper::KEY_TYPE> sorted_keys;
80 for(const InDetRawDataCollection<T_RDORawData>* collection : *origRdoContainer ) {
81 const IdentifierHash idHash = collection->identifyHash();
82 T_ModuleHelper module_helper( emulatedDefects->getDetectorElement(idHash).design() );
83 std::unique_ptr<InDetRawDataCollection<T_RDORawData> >
84 clone = std::make_unique<InDetRawDataCollection<T_RDORawData> >(idHash);
85 clone->setIdentifier(collection->identify());
86 unsigned int rejected_per_mod=0u;
87 unsigned int noise_per_mod=0u;
88 if (!emulatedDefects->isModuleDefect(idHash)) {
89 unsigned int n_cells = module_helper.nCells();
90 unsigned int n_noise_hits=rndmEngine && m_noiseParamIdx.at(idHash)<m_noiseProbability.size()
91 ? CLHEP::RandPoisson::shoot(rndmEngine,
92 n_cells * m_noiseProbability.value()[ m_noiseParamIdx[idHash] ] )
94 clone->reserve( collection->size() + n_noise_hits);
96 ATH_MSG_ERROR( "Not module design for " << idHash);
97 return StatusCode::FAILURE;
99 TH2 *h2_rejected_hits=nullptr;
100 TH2 *h2_noise_hits=nullptr;
101 TH1 *h1_noise_shape=nullptr;
102 if (m_histogrammingEnabled) {
103 std::lock_guard<std::mutex> lock(m_histMutex);
104 std::tuple<TH2 *, TH2 *, TH1 *> hists = findHist(module_helper.nSensorRows(), module_helper.nSensorColumns());
105 h2_rejected_hits=std::get<0>(hists);
106 h2_noise_hits=std::get<1>(hists);
107 h1_noise_shape=std::get<2>(hists);
111 sorted_keys.reserve( collection->size()+n_noise_hits);
112 for(const auto *const rdo : *collection) {
113 const Identifier rdoID = rdo->identify();
115 auto row_idx = id_helper.row_index(rdoID);
116 auto col_idx = id_helper.col_index(rdoID);
118 unsigned int n_new_hits = id_helper.cloneOrRejectHit( module_helper, *(emulatedDefects.cptr()), idHash, row_idx, col_idx, *rdo, *clone);
120 n_split_rdos += (n_new_hits-1);
121 for (unsigned int hit_i=n_new_hits; hit_i>0; --hit_i) {
122 auto new_hit = clone->at(clone->size()-hit_i);
124 const Identifier rdoID = new_hit->identify();
125 auto row_idx = id_helper.row_index(rdoID);
126 auto col_idx = id_helper.col_index(rdoID);
127 unsigned int nConsecutiveRows = id_helper.nConsecutiveRows(*rdo);
128 for (unsigned int row_seq_i=0; row_seq_i<nConsecutiveRows; ++row_seq_i) {
129 unsigned int key = module_helper.hardwareCoordinates(row_idx+row_seq_i,col_idx);
130 auto iter = std::lower_bound(sorted_keys.begin(), sorted_keys.end(), key);
131 if (iter == sorted_keys.end()) {
132 sorted_keys.push_back(key);
136 sorted_keys.insert(iter, key);
143 if (m_histogrammingEnabled && h2_rejected_hits) {
144 std::lock_guard<std::mutex> lock(m_histMutex);
145 h2_rejected_hits->Fill(col_idx, row_idx);
152 // add random noise hits
153 for (unsigned int i=0; i<n_noise_hits; ++i) {
154 for (unsigned int attempt_i=0; attempt_i<10; ++attempt_i) {
155 unsigned int cell_idx=CLHEP::RandFlat::shoot(rndmEngine,n_cells); // %pixels;
156 unsigned int row_idx = cell_idx % module_helper.rows();
157 unsigned int col_idx = cell_idx / module_helper.rows();
158 unsigned int key = module_helper.hardwareCoordinates(row_idx,col_idx);
159 if (emulatedDefects->isDefect(module_helper, idHash, row_idx, col_idx)) {
160 ++n_defect_noise_hits;
163 auto iter = std::lower_bound(sorted_keys.begin(), sorted_keys.end(), key);
164 if (iter == sorted_keys.end()) {
165 sorted_keys.push_back(key);
169 sorted_keys.insert(iter, key);
175 float prob = CLHEP::RandFlat::shoot(rndmEngine,1.);
176 assert( m_noiseParamIdx[idHash] < m_noiseShapeCummulative.size() );
177 const std::vector<float> &noise_shape = m_noiseShapeCummulative[ m_noiseParamIdx[idHash] ];
178 unsigned int noise_value=0;
179 for (noise_value=0; noise_value<noise_shape.size(); ++noise_value) {
180 if (noise_shape[noise_value]>prob) {
185 clone->push_back( id_helper.createNoiseHit( module_helper, collection->identify(), cell_idx, noise_value).release() );
186 unsigned int nConsecutiveRows = id_helper.nConsecutiveRows(*clone->back());
187 if (nConsecutiveRows!=1u) {
188 ATH_MSG_ERROR("Noise hit has group size larger than 1. This may create duplicate hits.");
191 if (m_histogrammingEnabled && h2_noise_hits) {
192 unsigned int row_idx = cell_idx % module_helper.rows();
193 unsigned int col_idx = cell_idx / module_helper.rows();
195 std::lock_guard<std::mutex> lock(m_histMutex);
196 h2_noise_hits->Fill(col_idx, row_idx);
197 h1_noise_shape->Fill(noise_value);
207 rejected_per_mod += collection->size();
209 if (m_histogrammingEnabled) {
210 std::lock_guard<std::mutex> lock(m_histMutex);
211 unsigned int bin_i=m_moduleHist[kRejectedHits]->GetBin( idHash%100+1, idHash/100+1);
212 assert(m_moduleHist[kRejectedHits]->GetNbinsX() == m_moduleHist[kNoiseHits]->GetNbinsX());
213 assert(m_moduleHist[kRejectedHits]->GetNbinsY() == m_moduleHist[kNoiseHits]->GetNbinsY());
214 m_moduleHist[kRejectedHits]->SetBinContent(bin_i, rejected_per_mod );
215 m_moduleHist[kNoiseHits]->SetBinContent(bin_i, noise_per_mod );
217 n_added_noise_hits += noise_per_mod;
218 n_rejected += rejected_per_mod;
219 n_new += clone->size();
220 rdoOutContainer->addCollection( clone.release(), idHash).ignore();
222 m_rejectedRDOs += n_rejected;
223 m_totalRDOs += n_new;
224 m_totalNoise += n_added_noise_hits;
225 m_splitRDOs += n_split_rdos;
226 ATH_MSG_DEBUG("rejected " << m_rejectedRDOs << ", copied " << m_totalRDOs << " RDOs"
227 << " noise " << n_added_noise_hits << " (+" << n_defect_noise_hits << ")"
228 << " split hits: " << n_split_rdos);
230 return StatusCode::SUCCESS;