ATLAS Offline Software
PixelDefectsEmulatorCondAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 // Silicon trackers includes
7 
8 #include "Identifier/Identifier.h"
14 
15 #include "StoreGate/WriteHandle.h"
16 #include <typeinfo>
17 
18 #include "CLHEP/Random/RandPoisson.h"
19 #include "CLHEP/Random/RandFlat.h"
20 
21 namespace {
22  unsigned int makeCheckerboard(unsigned int pixel_idx, unsigned int n_rows, unsigned int n_columns,
23  bool odd_row_toggle,
24  bool odd_col_toggle
25  ) {
26  unsigned int row_i=pixel_idx / n_columns;
27  unsigned int col_i = pixel_idx % n_columns;
28  unsigned int row_odd = row_i < n_rows/2 || !odd_row_toggle ? 1 : 0;
29  unsigned int div_row = n_rows/7;
30  unsigned int div_cols = n_columns/7;
31  row_i = std::min((((row_i / div_row ) & (0xffff-1)) + row_odd)*div_row + (row_i%div_row), n_rows-1);
32  unsigned int col_odd = col_i < n_columns/2 || !odd_col_toggle ? 1 : 0;
33  col_i = std::min((((col_i / div_cols ) & (0xffff-1)) + col_odd)*div_cols + (col_i%div_cols),n_columns-1);
34  pixel_idx= row_i * n_columns + (col_i % n_columns);
35  return pixel_idx;
36  }
37 
38  class MyLockGuard {
39  public:
40  MyLockGuard(std::mutex &a_mutex, bool disable)
41  : m_mutex( !disable ? &a_mutex : nullptr)
42  {
43  if (m_mutex) {m_mutex->lock(); }
44  }
45  ~MyLockGuard() {
46  if (m_mutex) {m_mutex->unlock(); }
47  }
48  private:
49  std::mutex *m_mutex;
50  };
51 }
52 
53 namespace InDet{
54  using namespace InDet;
55  PixelDefectsEmulatorCondAlg::PixelDefectsEmulatorCondAlg(const std::string &name, ISvcLocator *pSvcLocator) :
56  AthReentrantAlgorithm(name, pSvcLocator),
57  m_idHelper(nullptr) {}
58 
60  ATH_CHECK(m_rndmSvc.retrieve());
63  ATH_CHECK(detStore()->retrieve(m_idHelper,"PixelID"));
64  m_rngName = name()+"RandomEngine";
65 
66  if (!m_histSvc.name().empty() && !m_histogramGroupName.value().empty()) {
67  ATH_CHECK(m_histSvc.retrieve());
69  // allow histogramming for at most 6 different pixel module types
70  // histgram for additional module types will end up in the last histogram
71  constexpr unsigned int n_different_pixel_matrices_max=6;
72  m_dimPerHist.reserve(n_different_pixel_matrices_max);
73  m_hist.reserve(n_different_pixel_matrices_max);
74  std::array<TH2 *,3> hists {};
75  std::array<std::string,3> hist_name {"defects_per_module",
76  "corecolumn_defects_per_module",
77  "matrix_type_id_per_module"};
78  std::array<std::string,3> hist_title{"Defects per module",
79  "Core column defects per module",
80  "Matrix type id per module"};
81  for (unsigned int hist_i=0; hist_i<hists.size(); ++hist_i) {
82  // support idHashes from 0 to 10k
83  hists.at(hist_i) = new TH2F(hist_name.at(hist_i).c_str(), hist_title.at(hist_i).c_str(),
84  100, -0.5, 100-0.5,
85  100, -0.5, 100-0.5
86  );
87  hists[hist_i]->GetXaxis()->SetTitle("ID hash % 100");
88  hists[hist_i]->GetYaxis()->SetTitle("ID hash / 100");
89  if ( m_histSvc->regHist(m_histogramGroupName.value() + hists[hist_i]->GetName(),hists[hist_i]).isFailure() ) {
90  return StatusCode::FAILURE;
91  }
92  }
93  m_moduleDefectsHist = hists[0];
94  m_moduleCoreColDefectsHist = hists[1];
95  m_matrixHist = hists[2];
96  }
97 
98  return StatusCode::SUCCESS;
99  }
100 
102  return StatusCode::SUCCESS;
103  }
104 
105  StatusCode PixelDefectsEmulatorCondAlg::execute(const EventContext& ctx) const {
107  if (defectsOut.isValid()) {
108  return StatusCode::SUCCESS;
109  }
111 
112  defectsOut.addDependency(pixelDetEleColl);
113 
114  unsigned int n_pixel=0u;
115  unsigned int n_error=0u;
116  unsigned int max_n_defects=0u;
117  unsigned int max_n_col_group_defects=0u;
118  unsigned int n_col_group_defects_total=0u;
119  std::unique_ptr<InDet::PixelEmulatedDefects> defects = std::make_unique<InDet::PixelEmulatedDefects>();
120  defects->m_detectorElements=pixelDetEleColl.cptr();
121  defects->resize( pixelDetEleColl.cptr()->size());
122  unsigned int n_defects_total=0;
123  {
124  ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_rngName);
125  rngWrapper->setSeed( m_rngName, ctx );
126  CLHEP::HepRandomEngine *rndmEngine = rngWrapper->getEngine(ctx);
127  unsigned int module_i=0;
128  --module_i;
129 
130  for (const InDetDD::SiDetectorElement *det_ele: *(pixelDetEleColl.cptr())) {
131  ++module_i;
132  PixelModuleHelper helper(det_ele->design());
133 
134  if (!helper) {
135  ++n_error;
136  continue;
137  }
138  unsigned int pixels = helper.nPixels();
139  n_pixel += pixels;
140 
141  // bad to lock for the entire loop, but this algorithm is intended to run
142  // only once per job anyway
143  MyLockGuard lock(m_histMutex, m_histogrammingEnabled);
144  TH2 *h2=findHist(helper.nRows(), helper.nColumns());
145 
146  unsigned int n_col_group_defects=static_cast<unsigned int>(std::max(0,static_cast<int>(CLHEP::RandPoisson::shoot(rndmEngine,helper.nColumns()
147  * m_pixelColGroupdDefectProbability.value()))));
148  n_col_group_defects_total += n_col_group_defects;
149  max_n_col_group_defects = std::max(max_n_col_group_defects, n_col_group_defects);
150 
151  unsigned int n_defects=static_cast<unsigned int>(std::max(0,static_cast<int>(CLHEP::RandPoisson::shoot(rndmEngine,pixels * m_pixelDefectProbability.value()))));
152  max_n_defects = std::max(max_n_defects,n_defects);
153 
154  std::vector<unsigned int> &module_defects=(*defects).at(module_i);
155  module_defects.reserve(n_defects + n_col_group_defects);
156  for (unsigned int defect_i=0; defect_i < n_col_group_defects; ++defect_i) {
157  unsigned int pixel_idx=CLHEP::RandFlat::shoot(rndmEngine,pixels); // %pixels;
158 
159  // accumulate defects on checker board
160  if (m_checkerBoardToggle) {
161  pixel_idx=makeCheckerboard(pixel_idx,helper.nRows(), helper.nColumns(), m_oddRowToggle.value(), m_oddColToggle.value() );
162  }
163 
164  unsigned int key = helper.columnGroupDefect(pixel_idx / helper.nColumns(), pixel_idx % helper.nColumns());
165  auto [insert_iter,end_iter] = PixelEmulatedDefects::lower_bound( module_defects, key);
166  if (insert_iter == end_iter) {
167  module_defects.push_back(key);
168  if (h2) {
169  std::array<unsigned int,4> ranges_row_col = helper.offlineRange(key);
170  for (unsigned int row_i=ranges_row_col[0]; row_i<ranges_row_col[1]; ++row_i) {
171  for (unsigned int col_i=ranges_row_col[2]; col_i<ranges_row_col[3]; ++col_i) {
172  h2->Fill(col_i, row_i);
173  }
174  }
175  }
176 
177  }
178  else {
179  if (!helper.isSameDefectWithGroups(*insert_iter, key)) {
180  module_defects.insert( insert_iter, key);
181  if (h2) {
182  std::array<unsigned int,4> ranges_row_col = helper.offlineRange(key);
183  for (unsigned int row_i=ranges_row_col[0]; row_i<ranges_row_col[1]; ++row_i) {
184  for (unsigned int col_i=ranges_row_col[2]; col_i<ranges_row_col[3]; ++col_i) {
185  h2->Fill(col_i, row_i);
186  }
187  }
188  }
189  }
190  }
191  }
192  unsigned int n_col_group_defects_registered=module_defects.size();
193 
194  for (unsigned int defect_i=0; defect_i < n_defects; ++defect_i) {
195  unsigned int pixel_idx=CLHEP::RandFlat::shoot(rndmEngine,pixels); // %pixels;
196 
197  // accumulate defects on checker board
198  if (m_checkerBoardToggle) {
199  pixel_idx=makeCheckerboard(pixel_idx,helper.nRows(), helper.nColumns(), m_oddRowToggle.value(), m_oddColToggle.value());
200  }
201 
202  unsigned int key = helper.hardwareCoordinates(pixel_idx / helper.nColumns(), pixel_idx % helper.nColumns());
203  // order keys in descending order
204  // such that lower_bound with greater will return the matching element or the element before
205  auto [insert_iter,end_iter] = PixelEmulatedDefects::lower_bound( module_defects, key);
206  if (insert_iter == end_iter) {
207  module_defects.push_back(key);
208  if (h2) {
209  std::array<unsigned int,4> ranges_row_col = helper.offlineRange(key);
210  for (unsigned int row_i=ranges_row_col[0]; row_i<ranges_row_col[1]; ++row_i) {
211  for (unsigned int col_i=ranges_row_col[2]; col_i<ranges_row_col[3]; ++col_i) {
212  h2->Fill(col_i, row_i);
213  }
214  }
215  }
216  }
217  else if (helper.isSameDefectWithGroups(*insert_iter, key)) {
218  continue;
219  }
220  else {
221  module_defects.insert( insert_iter, key);
222  if (h2) {
223  std::array<unsigned int,4> ranges_row_col = helper.offlineRange(key);
224  for (unsigned int row_i=ranges_row_col[0]; row_i<ranges_row_col[1]; ++row_i) {
225  for (unsigned int col_i=ranges_row_col[2]; col_i<ranges_row_col[3]; ++col_i) {
226  h2->Fill(col_i, row_i);
227  }
228  }
229  }
230  }
231  }
233  // all the following histograms are expected to have the same binning
234  // i.e. one bin per ID hash organised in a matrix
235  unsigned int ids_per_col = static_cast<unsigned int>(m_moduleDefectsHist->GetNbinsX());
236  unsigned int bin_i=m_moduleDefectsHist->GetBin( module_i%ids_per_col+1, module_i/ids_per_col+1);
237  m_moduleDefectsHist->SetBinContent(bin_i, module_defects.size()-n_col_group_defects_registered );
238  m_moduleCoreColDefectsHist->SetBinContent(bin_i, n_col_group_defects_registered );
239  // get the matrix "ID"
240  for (unsigned int hist_i=0; hist_i < m_hist.size(); ++hist_i) {
241  if (m_hist[hist_i]==h2) {
242  m_matrixHist->SetBinContent(bin_i, hist_i+1);
243  break;
244  }
245  }
246  }
247  n_defects_total+=module_defects.size();
248  }
249  }
250 
251 
252  ATH_CHECK( defectsOut.record (std::move(defects)) );
253 
254  ATH_MSG_INFO("Total pixel " << n_pixel << " non-pixel modules " << n_error << " defects " << n_defects_total << " max /mod " << max_n_defects
255  << " core column defects " << n_col_group_defects_total << " max. / mod " << max_n_col_group_defects);
256 
257  return StatusCode::SUCCESS;
258  }
259 
260  TH2 *PixelDefectsEmulatorCondAlg::findHist(unsigned int n_rows, unsigned int n_cols) const {
261  unsigned int key=(n_rows << 16) | n_cols;
262  std::vector<unsigned int>::const_iterator iter = std::find(m_dimPerHist.begin(),m_dimPerHist.end(), key );
263  if (iter == m_dimPerHist.end()) {
264  if (m_dimPerHist.size() == m_dimPerHist.capacity()) {
265  if (m_dimPerHist.capacity()==0) {
266  return nullptr;
267  }
268  return m_hist.back();
269  }
270  else {
271  std::stringstream name;
272  name << "defects_" << (m_hist.size()+1) << "_" << n_rows << "_" << n_cols;
273  std::stringstream title;
274  title << "Defects for " << n_rows << "(rows) #times " << n_cols << " (columns) ID " << (m_hist.size()+1);
275  m_hist.push_back(new TH2F(name.str().c_str(), title.str().c_str(),
276  n_cols, -0.5, n_cols-0.5,
277  n_rows, -0.5, n_rows-0.5
278  ));
279  m_hist.back()->GetXaxis()->SetTitle("offline column");
280  m_hist.back()->GetYaxis()->SetTitle("offline row");
281  if ( m_histSvc->regHist(m_histogramGroupName.value() + name.str(),m_hist.back()).isFailure() ) {
282  throw std::runtime_error("Failed to register histogram.");
283  }
284  m_dimPerHist.push_back(key);
285  return m_hist.back();
286  }
287  }
288  else {
289  return m_hist.at(iter-m_dimPerHist.begin());
290  }
291  }
292 
293 }// namespace closure
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
PixelID.h
This is an Identifier helper class for the Pixel subdetector. This class is a factory for creating co...
ATHRNG::RNGWrapper::setSeed
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
Definition: RNGWrapper.h:169
InDet::PixelDefectsEmulatorCondAlg::PixelDefectsEmulatorCondAlg
PixelDefectsEmulatorCondAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition: PixelDefectsEmulatorCondAlg.cxx:55
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
InDet::PixelDefectsEmulatorCondAlg::m_checkerBoardToggle
Gaudi::Property< bool > m_checkerBoardToggle
Definition: PixelDefectsEmulatorCondAlg.h:57
InDet::PixelDefectsEmulatorCondAlg::m_rndmSvc
ServiceHandle< IAthRNGSvc > m_rndmSvc
Definition: PixelDefectsEmulatorCondAlg.h:40
InDet::PixelDefectsEmulatorCondAlg::m_histSvc
ServiceHandle< ITHistSvc > m_histSvc
Definition: PixelDefectsEmulatorCondAlg.h:59
PixelDefectsEmulatorCondAlg.h
InDet::PixelModuleHelper
Helper class to convert between offline column, row and hardware chip, column, row coordinates.
Definition: PixelModuleHelper.h:33
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
InDet
Primary Vertex Finder.
Definition: VP1ErrorUtils.h:36
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
InDet::PixelDefectsEmulatorCondAlg::m_histMutex
std::mutex m_histMutex
Definition: PixelDefectsEmulatorCondAlg.h:68
InDet::PixelDefectsEmulatorCondAlg::m_pixelDetEleCollKey
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_pixelDetEleCollKey
Definition: PixelDefectsEmulatorCondAlg.h:42
InDet::PixelDefectsEmulatorCondAlg::m_pixelDefectProbability
Gaudi::Property< float > m_pixelDefectProbability
Definition: PixelDefectsEmulatorCondAlg.h:44
InDet::PixelDefectsEmulatorCondAlg::m_pixelColGroupdDefectProbability
Gaudi::Property< float > m_pixelColGroupdDefectProbability
Definition: PixelDefectsEmulatorCondAlg.h:46
SG::WriteCondHandle::record
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
Definition: WriteCondHandle.h:157
InDet::PixelDefectsEmulatorCondAlg::m_histogrammingEnabled
bool m_histogrammingEnabled
Definition: PixelDefectsEmulatorCondAlg.h:77
python.TrigEgammaMonitorHelper.TH2F
def TH2F(name, title, nxbins, bins_par2, bins_par3, bins_par4, bins_par5=None, bins_par6=None, path='', **kwargs)
Definition: TrigEgammaMonitorHelper.py:45
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:77
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
InDet::PixelDefectsEmulatorCondAlg::m_idHelper
const PixelID * m_idHelper
Definition: PixelDefectsEmulatorCondAlg.h:63
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
runBeamSpotCalibration.helper
helper
Definition: runBeamSpotCalibration.py:112
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.
PixelRDORawData.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
InDet::PixelDefectsEmulatorCondAlg::m_oddRowToggle
Gaudi::Property< bool > m_oddRowToggle
Definition: PixelDefectsEmulatorCondAlg.h:53
covarianceTool.title
title
Definition: covarianceTool.py:542
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MakeTH3DFromTH2Ds.hists
hists
Definition: MakeTH3DFromTH2Ds.py:72
InDet::PixelDefectsEmulatorCondAlg::finalize
virtual StatusCode finalize() override final
Definition: PixelDefectsEmulatorCondAlg.cxx:101
DeMoScan.defects
defects
Definition: DeMoScan.py:297
InDet::PixelDefectsEmulatorCondAlg::findHist
TH2 * findHist(unsigned int n_rows, unsigned int n_cols) const
Definition: PixelDefectsEmulatorCondAlg.cxx:260
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
ATHRNG::RNGWrapper
A wrapper class for event-slot-local random engines.
Definition: RNGWrapper.h:56
InDet::PixelDefectsEmulatorCondAlg::m_oddColToggle
Gaudi::Property< bool > m_oddColToggle
Definition: PixelDefectsEmulatorCondAlg.h:55
InDet::PixelDefectsEmulatorCondAlg::initialize
virtual StatusCode initialize() override final
Definition: PixelDefectsEmulatorCondAlg.cxx:59
InDet::PixelDefectsEmulatorCondAlg::m_histogramGroupName
Gaudi::Property< std::string > m_histogramGroupName
Definition: PixelDefectsEmulatorCondAlg.h:61
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
SiDetectorElement.h
InDet::EmulatedDefects< PixelModuleHelper >::lower_bound
static std::pair< std::vector< unsigned int >::iterator, std::vector< unsigned int >::iterator > lower_bound(std::vector< unsigned int > &module_defects, unsigned int key)
Convenience method to find the preceding defect.
Definition: EmulatedDefects.h:46
ATHRNG::RNGWrapper::getEngine
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition: RNGWrapper.h:134
RNGWrapper.h
PixelModuleDesign.h
SG::WriteCondHandle::isValid
bool isValid() const
Definition: WriteCondHandle.h:248
InDet::PixelDefectsEmulatorCondAlg::m_writeKey
SG::WriteCondHandleKey< InDet::PixelEmulatedDefects > m_writeKey
Definition: PixelDefectsEmulatorCondAlg.h:48
SG::WriteCondHandle
Definition: WriteCondHandle.h:26
InDet::PixelDefectsEmulatorCondAlg::execute
virtual StatusCode execute(const EventContext &ctx) const override final
Definition: PixelDefectsEmulatorCondAlg.cxx:105
InDet::PixelDefectsEmulatorCondAlg::m_rngName
std::string m_rngName
Definition: PixelDefectsEmulatorCondAlg.h:64
SG::WriteCondHandle::addDependency
void addDependency(const EventIDRange &range)
Definition: WriteCondHandle.h:275
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
SG::ReadCondHandle::cptr
const_pointer_type cptr()
Definition: ReadCondHandle.h:67