ATLAS Offline Software
ITkStripFrontEnd.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "ITkStripFrontEnd.h"
6 
10 
11 
12 // Random number
13 #include "CLHEP/Random/RandFlat.h"
14 #include "CLHEP/Random/RandGaussZiggurat.h" // for RandGaussZiggurat
15 #include "CLHEP/Random/RandPoisson.h"
16 
17 #include "CLHEP/Random/RandomEngine.h"
18 
19 using namespace InDetDD;
20 
21 // constructor
22 ITkStripFrontEnd::ITkStripFrontEnd(const std::string& type, const std::string& name, const IInterface* parent)
23  : base_class(type, name, parent) {
24 }
25 
26 // ----------------------------------------------------------------------
27 // Initialize
28 // ----------------------------------------------------------------------
30  if (m_NoiseOn and (not m_analogueNoiseOn)) {
31  ATH_MSG_FATAL("AnalogueNoiseOn/m_analogueNoiseOn should be true if NoiseOn/m_NoiseOn is true.");
32  return StatusCode::FAILURE;
33  }
34 
35  ATH_MSG_DEBUG("ITkStripFrontEnd::initialize()");
36  // Get SCT helper
37  ATH_CHECK(detStore()->retrieve(m_ITkStripId, "SCT_ID"));
38  // Get SCT detector manager
40 
41  ATH_CHECK(m_strip_amplifier.retrieve());
42 
43  constexpr float fC = 6242.2;
44  m_Threshold = m_Threshold * fC;
45 
46  // Check configuration. If it is invalid, abort this job.
50  ATH_MSG_FATAL("m_data_compression_mode = " << m_data_compression_mode
51  << " is invalid. Abort this job!!!");
52  return StatusCode::FAILURE;
53  }
55  ATH_MSG_FATAL("m_data_readout_mode = " << m_data_readout_mode
56  << " is invalid. Abort this job!!!");
57  return StatusCode::FAILURE;
58  }
61  ATH_MSG_FATAL("m_data_compression_mode = " << m_data_compression_mode
62  << (m_data_compression_mode==Level_X1X ? " (Level_X1X)" : " (AnyHit_1XX_X1X_XX1)")
63  << " requires timing information."
64  << " However, m_data_readout_mode = " << m_data_readout_mode
65  << " (Condensed) does not keep timing information. Abort this job!!!");
66  return StatusCode::FAILURE;
67  }
68 
69  return StatusCode::SUCCESS;
70 }
71 
72 // ----------------------------------------------------------------------
73 // Init the class variable vectors
74 // ----------------------------------------------------------------------
76  data.m_GainFactor.resize(strips);
77 
78  data.m_Analogue[0].resize(strips);
79  data.m_Analogue[1].resize(strips);
80  data.m_Analogue[2].resize(strips);
81 
82 }
83 
84 
85 // ----------------------------------------------------------------------
86 // process the collection of pre digits this will need to go through
87 // all single-strip pre-digits calculate the amplifier response add noise
88 // (this could be moved elsewhere later) apply threshold do clustering
89 // ----------------------------------------------------------------------
90 void
91 ITkStripFrontEnd::process(SiChargedDiodeCollection& collection, CLHEP::HepRandomEngine* /*rndmEngine*/) const {
92  // get ITk module side design
93  [[maybe_unused]] const SCT_ModuleSideDesign *p_design = static_cast<const SCT_ModuleSideDesign*>(&(collection.design()));
94 
96 
97  // Check number of strips in design and from manager(max number of strips on any module)
98  // The design value should always be equal or lower than the manager one
99  // However, no resising is now done in case of a lower value
100  const int strip_max = p_design->cells();
101 
102  // Init vectors
103  initVectors(strip_max, data);
104 
105  // Contains strip hit info, reset to 0 for each wafer processed
106  data.m_StripHitsOnWafer.assign(strip_max, 0);
107 
108  // data.m_Analogue were cleared in initVectors().
109 
110  // Check if collection empty
111  if (not collection.empty()) {
112  //Commented parts are future Tools to be added
113  // Setup gain/offset/noise to the hit and neighbouring strips// Use JO values
114  // if (StatusCode::SUCCESS != prepareGainAndOffset(collection, moduleId, rndmEngine, data, strip_max)) {
115  // ATH_MSG_ERROR("\tCan't prepare Gain and Offset");
116  // }
117 
118  doSignalChargeForHits(collection, data, strip_max);
119 
120  doThresholdCheckForRealHits(collection, data, strip_max);
121 
122  // if (StatusCode::SUCCESS != doThresholdCheckForCrosstalkHits(collection, data, strip_max)) {
123  // ATH_MSG_ERROR("\tCan't doThresholdCheckForCrosstalkHits");
124  // }
125  }
126 
127  // if (m_NoiseOn) {
128  // if (StatusCode::SUCCESS != randomNoise(collection, moduleId, rndmEngine, data,strip_max)) {
129  // ATH_MSG_ERROR("\tCan't do random noise on wafer?!");
130  // }
131  // }
132 
133  // // Check for strips above threshold and do clustering
134  // if (StatusCode::SUCCESS != doClustering(collection, data,strip_max)) {
135  // ATH_MSG_ERROR("\tCan't cluster the hits?!");
136  // }
137 
138 }
139 
140 
142  using list_t = SiTotalCharge::list_t;
143 
144  // *****************************************************************************
145  // Loop over the diodes (strips ) and for each of them define the total signal
146  // *****************************************************************************
147 
148  // set up number of needed bins depending on the compression mode
149  short bin_max = 0;
151  bin_max = m_data_compression_mode;
152  } else {
153  bin_max = 3;
154  }
155 
156  std::vector<float> response(bin_max);
157 
158  for (auto& [blub, diode]: collection) {
159  // should be const as we aren't trying to change it here - but getReadoutCell() is not a const method...
160  unsigned int flagmask = diode.flag() & 0xFE;
161  // Get the flag for this diode ( if flagmask = 1 If diode is disconnected/disabled skip it)
162  if (!flagmask) { // If the diode is OK (not flagged)
163  const SiReadoutCellId &roCell = diode.getReadoutCell();
164 
165  if (roCell.isValid()) {
166  int strip = roCell.strip();
167 
168  [[maybe_unused]] const list_t &ChargesOnStrip = diode.totalCharge().chargeComposition();
169 
171  // Amplifier response
172  // m_sct_amplifier->response(ChargesOnStrip, m_timeOfThreshold, response);
173  for (short bin = 0; bin < bin_max; ++bin) {
174  data.m_Analogue[bin][strip] += data.m_GainFactor[strip] * response[bin];
175  }
176  // Add Crosstalk signal for neighboring strip
177  // m_sct_amplifier->crosstalk(ChargesOnStrip, m_timeOfThreshold, response);
178  for (short bin = 0; bin < bin_max; ++bin) {
179  if (strip + 1 < strip_max) {
180  data.m_Analogue[bin][strip + 1] += data.m_GainFactor[strip + 1] * response[bin];
181  }
182  if (strip > 0) {
183  data.m_Analogue[bin][strip - 1] += data.m_GainFactor[strip - 1] * response[bin];
184  }
185  }
186  } else { // Expanded
187  // Amplifier response
188  // m_sct_amplifier->response(ChargesOnStrip, m_timeOfThreshold, response);
189  for (short bin = 0; bin < bin_max; ++bin) {
190  data.m_Analogue[bin][strip] += data.m_GainFactor[strip] * response[bin];
191  }
192  // Add Crosstalk signal for neighboring strip
193  // m_sct_amplifier->crosstalk(ChargesOnStrip, m_timeOfThreshold, response);
194  for (short bin = 0; bin < bin_max; ++bin) {
195  if (strip + 1 < strip_max) {
196  data.m_Analogue[bin][strip + 1] += data.m_GainFactor[strip + 1] * response[bin];
197  }
198  if (strip > 0) {
199  data.m_Analogue[bin][strip - 1] += data.m_GainFactor[strip - 1] * response[bin];
200  }
201  }
202  }
203  } else { // if roCell not valid
204  ATH_MSG_WARNING("\t Cannot get the cell ");
205  }
206  } else {// If diode is disconnected/disabled skip it
207  ATH_MSG_WARNING("\tDisabled or disconnected diode (strip)");
208  }
209  }
210 }
211 
212 
214  // **********************************************************************************
215  // Flag strips below threshold and flag the threshold check into data.m_StripHitsOnWafer
216  // **********************************************************************************
217 
218  for (auto& [blub, diode]: collection) {
219  const SiReadoutCellId & roCell = diode.getReadoutCell();
220  if (roCell.isValid()) {
221  int strip = roCell.strip();
222  if (strip > -1 and strip < strip_max) {
224  if ((data.m_Analogue[0][strip] >= m_Threshold or data.m_Analogue[1][strip] < m_Threshold)) {
225  SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
226  data.m_StripHitsOnWafer[strip] = -1;
227  } else if (((0x10 & diode.flag()) == 0x10) or ((0x4 & diode.flag()) == 0x4)) {
228  // previously a crazy strip number could have screwed things up here.
229  data.m_StripHitsOnWafer[strip] = -1;
230  } else {
231  data.m_StripHitsOnWafer[strip] = 1;
232  SiHelper::SetTimeBin(diode, 2, &msg()); // set timebin info
233  }
234  } else { // Expanded
235  int have_hit_bin = 0;
236  if (data.m_Analogue[0][strip] >= m_Threshold) {
237  have_hit_bin = 4;
238  }
239  if (data.m_Analogue[1][strip] >= m_Threshold) {
240  have_hit_bin += 2;
241  }
242  if (data.m_Analogue[2][strip] >= m_Threshold) {
243  have_hit_bin += 1;
244  }
245  if (((0x10 & diode.flag()) == 0x10) || ((0x4 & diode.flag()) == 0x4)) {
246  // previously a crazy strip number could have screwed things up here.
247  data.m_StripHitsOnWafer[strip] = -1;
248  } else if (m_data_compression_mode == Level_X1X) { // !< level and expanded mode
249  if (have_hit_bin == 2 or have_hit_bin == 3 or have_hit_bin == 6 or have_hit_bin == 7) {
250  data.m_StripHitsOnWafer[strip] = 1;
251  SiHelper::SetTimeBin(diode, have_hit_bin, &msg());
252  } else {
253  SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
254  data.m_StripHitsOnWafer[strip] = -1;
255  }
256  } else if (m_data_compression_mode == Edge_01X) { // !< edge and expanded mode
257  if (have_hit_bin == 2 or have_hit_bin == 3) {
258  data.m_StripHitsOnWafer[strip] = 1;
259  SiHelper::SetTimeBin(diode, have_hit_bin, &msg());
260  } else {
261  SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
262  data.m_StripHitsOnWafer[strip] = -1;
263  }
264  } else if (m_data_compression_mode == AnyHit_1XX_X1X_XX1) { // !< any hit mode
265  if (have_hit_bin == 0) {
266  SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
267  data.m_StripHitsOnWafer[strip] = -1;
268  } else {
269  data.m_StripHitsOnWafer[strip] = 1;
270  if (m_data_readout_mode == Expanded) { // !< check for exp mode or not
271  SiHelper::SetTimeBin(diode, have_hit_bin, &msg());
272  } else {
273  SiHelper::SetTimeBin(diode, 2, &msg());
274  }
275  }
276  }
277  }
278  }
279  }
280  }
281 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
ITkStripFrontEnd::ITkStripFrontEnd
ITkStripFrontEnd(const std::string &type, const std::string &name, const IInterface *parent)
constructor
Definition: ITkStripFrontEnd.cxx:22
ITkStripFrontEnd::doSignalChargeForHits
void doSignalChargeForHits(SiChargedDiodeCollection &collectione, ITkStripFrontEndData &data, const int &stripMax) const
Definition: ITkStripFrontEnd.cxx:141
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
ITkStripFrontEnd::m_detMgrName
StringProperty m_detMgrName
Definition: ITkStripFrontEnd.h:99
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
SCT_ID.h
This is an Identifier helper class for the SCT subdetector. This class is a factory for creating comp...
ITkStripFrontEnd::m_analogueNoiseOn
BooleanProperty m_analogueNoiseOn
Definition: ITkStripFrontEnd.h:86
SiliconTech::strip
@ strip
ITkStripFrontEnd::Expanded
@ Expanded
Definition: ITkStripFrontEnd.h:71
ITkStripFrontEnd::Level_X1X
@ Level_X1X
Definition: ITkStripFrontEnd.h:70
response
MDT_Response response
Definition: MDT_ResponseTest.cxx:28
SCT_ModuleSideDesign.h
InDetDD::SCT_ModuleSideDesign
Definition: SCT_ModuleSideDesign.h:40
ITkStripFrontEnd::process
virtual void process(SiChargedDiodeCollection &collection, CLHEP::HepRandomEngine *rndmEngine) const override
use the baseclass default finalize
Definition: ITkStripFrontEnd.cxx:91
InDetDD::SiCellId::isValid
bool isValid() const
Test if its in a valid state.
Definition: SiCellId.h:136
bin
Definition: BinsDiffFromStripMedian.h:43
ITkStripFrontEnd::m_ITkStripMgr
const InDetDD::SCT_DetectorManager * m_ITkStripMgr
Handle to SCT detector manager, also valid for ITkStrips.
Definition: ITkStripFrontEnd.h:97
SiChargedDiodeCollection::empty
bool empty() const
Definition: SiChargedDiodeCollection.h:274
InDetDD::SiCellId::strip
int strip() const
Get strip number. Equivalent to phiIndex().
Definition: SiCellId.h:131
SiTotalCharge::list_t
std::vector< SiCharge > list_t
Definition: SiTotalCharge.h:31
InDetDD::SCT_ModuleSideDesign::cells
int cells() const
number of readout stips within module side:
Definition: SCT_ModuleSideDesign.h:228
ITkStripFrontEnd::initialize
virtual StatusCode initialize() override
AlgTool initialize.
Definition: ITkStripFrontEnd.cxx:29
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
ITkStripFrontEnd::Condensed
@ Condensed
Definition: ITkStripFrontEnd.h:71
ITkStripFrontEnd::initVectors
void initVectors(int strips, ITkStripFrontEndData &data) const
Definition: ITkStripFrontEnd.cxx:75
ITkStripFrontEnd::m_strip_amplifier
ToolHandle< IAmplifier > m_strip_amplifier
Handle the Amplifier tool.
Definition: ITkStripFrontEnd.h:94
SiChargedDiodeCollection
Definition: SiChargedDiodeCollection.h:109
ITkStripFrontEnd::AnyHit_1XX_X1X_XX1
@ AnyHit_1XX_X1X_XX1
Definition: ITkStripFrontEnd.h:70
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
SiHelper::SetTimeBin
static void SetTimeBin(SiChargedDiode &chDiode, int time, MsgStream *log=nullptr)
Definition: SiHelper.h:149
SiHelper::belowThreshold
static void belowThreshold(SiChargedDiode &chDiode, bool flag, bool mask=false)
Definition: SiHelper.h:84
ITkStripFrontEnd::doThresholdCheckForRealHits
void doThresholdCheckForRealHits(SiChargedDiodeCollection &collectione, ITkStripFrontEndData &data, const int &stripMax) const
Definition: ITkStripFrontEnd.cxx:213
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ITkStripFrontEndData
simulation of the ITk Strips front-end electronics working as a SiPreDigitsProcessor models response ...
Definition: ITkStripFrontEnd.h:34
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
ITkStripFrontEnd::m_ITkStripId
const SCT_ID * m_ITkStripId
Handle to SCT ID helper also valid for ITkStrips.
Definition: ITkStripFrontEnd.h:98
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
ITkStripFrontEnd.h
plotBeamSpotVxVal.bin
int bin
Definition: plotBeamSpotVxVal.py:82
ITkStripFrontEnd::m_data_readout_mode
ShortProperty m_data_readout_mode
Definition: ITkStripFrontEnd.h:93
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
InDetDD
Message Stream Member.
Definition: FakeTrackBuilder.h:8
ITkStripFrontEnd::m_Threshold
FloatProperty m_Threshold
Definition: ITkStripFrontEnd.h:90
ITkStripFrontEnd::m_data_compression_mode
ShortProperty m_data_compression_mode
Definition: ITkStripFrontEnd.h:92
ITkStripFrontEnd::m_NoiseOn
BooleanProperty m_NoiseOn
Definition: ITkStripFrontEnd.h:85
InDetDD::SiReadoutCellId
Definition: SiReadoutCellId.h:42
SCT_DetectorManager.h
ITkStripFrontEnd::Edge_01X
@ Edge_01X
Definition: ITkStripFrontEnd.h:70
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
SiChargedDiodeCollection::design
const InDetDD::DetectorDesign & design() const
Definition: SiChargedDiodeCollection.h:224