Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
FEI4SimTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3  */
4 #include "FEI4SimTool.h"
6 
7 #include "PixelConditionsData/ChargeCalibParameters.h" //for Thresholds
11 
15 //
16 #include "CLHEP/Random/RandGaussZiggurat.h"
17 #include "CLHEP/Random/RandFlat.h"
18 #include "PixelNoiseFunctions.h"
19 #include <array>
20 #include <algorithm>
21 
22 
23 using namespace PixelDigitization;
24 
25 
26 
27 namespace{
28  double
29  getSigma(int tot){
30  constexpr std::array<double,17> sigmas{0.0,0.50,0.50,0.50,0.50,0.50,0.60,0.60,0.60,0.60,0.65,0.70,0.75,0.80,0.80,0.80,0.80};
31  return sigmas.at(tot);
32  }
33 
34 }
35 
36 
37 
38 FEI4SimTool::FEI4SimTool(const std::string& type, const std::string& name, const IInterface* parent) :
40 }
41 
42 FEI4SimTool::~FEI4SimTool() = default;
43 
46  ATH_MSG_DEBUG("FEI4SimTool::initialize()");
48 
49  return StatusCode::SUCCESS;
50 }
51 
53  ATH_MSG_DEBUG("FEI4SimTool::finalize()");
54  return StatusCode::SUCCESS;
55 }
56 
58  CLHEP::HepRandomEngine* rndmEngine) const {
59  const InDetDD::PixelModuleDesign* p_design =
60  static_cast<const InDetDD::PixelModuleDesign*>(&(chargedDiodes.element())->design());
61 
63  return;
64  }
65 
66  const PixelID* pixelId = static_cast<const PixelID*>(chargedDiodes.element()->getIdHelper());
67  const IdentifierHash moduleHash = pixelId->wafer_hash(chargedDiodes.identify()); // wafer hash
68  Identifier moduleID = pixelId->wafer_id(chargedDiodes.element()->identify());
69 
70  int barrel_ec = pixelId->barrel_ec(chargedDiodes.element()->identify());
71  int layerIndex = pixelId->layer_disk(chargedDiodes.element()->identify());
72 
73  if (std::abs(barrel_ec) != m_BarrelEC) {
74  return;
75  }
76 
77  const EventContext& ctx{Gaudi::Hive::currentContext()};
79  const PixelModuleData *moduleData = *moduleDataHandle;
81  const PixelChargeCalibCondData *calibData = *calibDataHandle;
82 
83  int maxFEI4SmallHit = 2;
84  int overflowToT = calibData->getFEI4OverflowToT();
85 
86  std::vector<std::unique_ptr<Pixel1RawData>> p_rdo_small_fei4;
87  int nSmallHitsFEI4 = 0;
88  std::vector<int> row, col;
89  const int maxRow = p_design->rowsPerCircuit();
90  const int maxCol = p_design->columnsPerCircuit();
91  std::vector<std::vector<int> > FEI4Map(maxRow + 16, std::vector<int>(maxCol + 16));
92 
93  // Add cross-talk
94  crossTalk(moduleData->getCrossTalk(barrel_ec, layerIndex), chargedDiodes);
95 
96  if (m_doNoise) {
97  // Add thermal noise
98  thermalNoise(m_thermalNoise, chargedDiodes, rndmEngine);
99 
100  // Add random noise
101  randomNoise(chargedDiodes, moduleData, m_numberOfBcid, calibData, rndmEngine, m_pixelReadout.get());
102  }
103 
104  // Add random diabled pixels
105  randomDisable(chargedDiodes, moduleData, rndmEngine); // FIXME How should we handle disabling pixels in Overlay jobs?
106 
107  for (SiChargedDiodeOrderedIterator i_chargedDiode = chargedDiodes.orderedBegin();
108  i_chargedDiode != chargedDiodes.orderedEnd(); ++i_chargedDiode) {
109  SiChargedDiode& diode = **i_chargedDiode;
110 
111  Identifier diodeID = chargedDiodes.getId(diode.diode());
112  double charge = diode.charge();
113 
114  // charge scaling function applied. (Reference: ATL-COM-INDET-2018-052)
115 
116  double corrQ = 1.11 *
117  (1.0 - (-7.09 * 1000.0) / (23.72 * 1000.0 + charge) + (-0.22 * 1000.0) /
118  (-0.42 * 1000.0 + charge));
119  if (corrQ < 1.0) {
120  corrQ = 1.0;
121  }
122  charge *= 1.0 / corrQ;
123 
124  //could scale if necessary
125 
126  unsigned int FE = m_pixelReadout->getFE(diodeID, moduleID);
127  InDetDD::PixelDiodeType type = m_pixelReadout->getDiodeType(diodeID);
128  if ((FE == InDetDD::invalidFrontEnd) or (type == InDetDD::PixelDiodeType::NONE)) continue;//invalid frontend
129 
130  // Apply analog threshold, timing simulation
131  const auto & thresholds = calibData->getThresholds(type, moduleHash, FE);
132  double threshold = PixelDigitization::randomThreshold(thresholds, rndmEngine);
133  // This noise check is unaffected by digitizationFlags.doInDetNoise in
134  // 21.0 - see PixelCellDiscriminator.cxx in that branch
135 
136  if (charge > threshold) {
137  int bunchSim;
138  if (diode.totalCharge().fromTrack()) {
139  bunchSim =
140  static_cast<int>(std::floor((getG4Time(diode.totalCharge()) +
142  } else {
143  bunchSim = CLHEP::RandFlat::shootInt(rndmEngine, m_numberOfBcid);
144  }
145 
146  if (bunchSim < 0 || bunchSim > m_numberOfBcid) {
147  SiHelper::belowThreshold(diode, true, true);
148  } else {
149  SiHelper::SetBunch(diode, bunchSim);
150  }
151  } else {
152  SiHelper::belowThreshold(diode, true, true);
153  }
154 
155  // charge to ToT conversion
156  double tot = calibData->getToT(type, moduleHash, FE, charge);
157  double totsig = calibData->getTotRes(moduleHash, FE, tot);
158  int nToT = static_cast<int>(CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot, totsig));
159 
160  // This is for new IBL calibration, since above method (stat_cast) is not effective.
161  if (totsig==0.0) {
162  double totIBLsig = getSigma(nToT);
163  if (totIBLsig) {
164  if (CLHEP::RandFlat::shoot(rndmEngine,0.0,1.0)<std::exp(-0.5/totIBLsig/totIBLsig)) {
165  if (CLHEP::RandFlat::shoot(rndmEngine,0.0,1.0)<0.5) { nToT--; }
166  else { nToT++; }
167  }
168  }
169  }
170 
171 
172 
173  // FEI4 HitDiscConfig
174  if (nToT == 2 && maxFEI4SmallHit == 2) {
175  nToT = 1;
176  }
177 
178  nToT=std::clamp(nToT, 1, overflowToT);
179 
180  if (nToT <= moduleData->getToTThreshold(barrel_ec, layerIndex)) {
181  SiHelper::belowThreshold(diode, true, true);
182  }
183 
184  // Filter events
185  if (SiHelper::isMaskOut(diode)) {
186  continue;
187  }
188  if (SiHelper::isDisabled(diode)) {
189  continue;
190  }
191 
192  if (!m_pixelConditionsTool->isActive(moduleHash, diodeID, ctx)) {
193  SiHelper::disabled(diode, true, true);
194  continue;
195  }
196 
197  int flag = diode.flag();
198  int bunch = (flag >> 8) & 0xff;
199 
200  InDetDD::SiReadoutCellId cellId = diode.getReadoutCell();
201  const Identifier id_readout = chargedDiodes.element()->identifierFromCellId(cellId);
202 
203  int iirow = cellId.phiIndex();
204  int iicol = cellId.etaIndex();
205  if (iicol >= maxCol) {
206  iicol = iicol - maxCol;
207  } // FEI4 copy mechanism works per FE.
208 
209  // Front-End simulation
210  if (bunch >= 0 && bunch < m_numberOfBcid) {
211  auto p_rdo = std::make_unique<Pixel1RawData>(id_readout, nToT, bunch, 0, bunch);
212  if (nToT > maxFEI4SmallHit) {
213  rdoCollection.push_back(p_rdo.release());
214  FEI4Map[iirow][iicol] = 2; //Flag for "big hits"
215  } else {
216  p_rdo_small_fei4.push_back(std::move(p_rdo));
217  row.push_back(iirow);
218  col.push_back(iicol);
219  FEI4Map[iirow][iicol] = 1; //Flag for low hits
220  nSmallHitsFEI4++;
221  }
222  }
223  }
224 
225  // Copy mechanism for IBL small hits:
226  if (nSmallHitsFEI4 > 0) {
227  bool recorded = false;
228 
229  //First case: Record small hits which are in the same Pixel Digital Region than a big hit:
230  for (int ismall = 0; ismall < nSmallHitsFEI4; ismall++) {
231  int rowPDR = row[ismall] / 2;
232  int colPDR = col[ismall] / 2;
233  for (int rowBigHit = 2 * rowPDR; rowBigHit != 2 * rowPDR + 2 && rowBigHit < maxRow; ++rowBigHit) {
234  for (int colBigHit = 2 * colPDR; colBigHit != 2 * colPDR + 2 && colBigHit < maxCol; ++colBigHit) {
236  "rowBig = " << rowBigHit << " colBig = " << colBigHit << " Map Content = " <<
237  FEI4Map[rowBigHit][colBigHit]);
238  if (FEI4Map[rowBigHit][colBigHit] == 2 && !recorded) {
239  rdoCollection.push_back(p_rdo_small_fei4[ismall].release());
240  recorded = true;
241  }
242  }
243  }
244 
245  // Second case: Record small hits which are phi-neighbours with a big hit:
246  if (!recorded && row[ismall] < maxRow - 1) {
247  if (FEI4Map[row[ismall] + 1][col[ismall]] == 2) {
248  rdoCollection.push_back(p_rdo_small_fei4[ismall].release());
249  recorded = true;
250  }
251  }
252  if (!recorded && row[ismall] != 0) {
253  if (FEI4Map[row[ismall] - 1][col[ismall]] == 2) {
254  rdoCollection.push_back(p_rdo_small_fei4[ismall].release());
255  recorded = true;
256  }
257  }
258  }
259  }
260  }
PixelID.h
This is an Identifier helper class for the Pixel subdetector. This class is a factory for creating co...
query_example.row
row
Definition: query_example.py:24
FEI4SimTool::initialize
virtual StatusCode initialize()
Definition: FEI4SimTool.cxx:44
PixelChargeCalibCondData::getToT
float getToT(InDetDD::PixelDiodeType type, unsigned int moduleHash, unsigned int FE, float Q) const
Definition: PixelChargeCalibCondData.cxx:174
SiChargedDiode
Definition: SiChargedDiode.h:30
FEI4SimTool::FEI4SimTool
FEI4SimTool()
PixelNoiseFunctions.h
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
SiChargedDiodeCollection::element
const InDetDD::SolidStateDetectorElementBase * element() const
Definition: SiChargedDiodeCollection.h:218
InDetDD::PixelModuleDesign
Definition: PixelModuleDesign.h:48
SiHelper::isDisabled
static bool isDisabled(SiChargedDiode &chDiode)
Definition: SiHelper.h:179
PixelID::barrel_ec
int barrel_ec(const Identifier &id) const
Values of different levels (failure returns 0)
Definition: PixelID.h:619
PixelModuleData::getCrossTalk
double getCrossTalk(int barrel_ec, int layer) const
Definition: PixelModuleData.cxx:129
FEI4SimTool::m_moduleDataKey
SG::ReadCondHandleKey< PixelModuleData > m_moduleDataKey
Definition: FEI4SimTool.h:33
PixelChargeCalibCondData::getThresholds
PixelChargeCalib::Thresholds getThresholds(InDetDD::PixelDiodeType type, unsigned int moduleHash, unsigned int FE) const
Definition: PixelChargeCalibCondData.cxx:99
PixelModuleData
Definition: PixelModuleData.h:22
FrontEndSimTool::m_thermalNoise
double m_thermalNoise
Definition: FrontEndSimTool.h:54
InDetDD::invalidFrontEnd
constexpr uint32_t invalidFrontEnd
Definition: PixelReadoutDefinitions.h:47
SiChargedDiode::getReadoutCell
const InDetDD::SiReadoutCellId & getReadoutCell() const
Definition: SiChargedDiode.h:111
InDetDD::PixelDiodeType
PixelDiodeType
Definition: PixelReadoutDefinitions.h:28
ChargeCalibParameters.h
Structs for holding charge calibration parameterisation and data.
SiChargedDiodeCollection::orderedEnd
SiChargedDiodeOrderedIterator orderedEnd()
Definition: SiChargedDiodeCollection.h:266
InDetDD::SiCellId::phiIndex
int phiIndex() const
Get phi index. Equivalent to strip().
Definition: SiCellId.h:122
PixelChargeCalibCondData::getTotRes
float getTotRes(unsigned int moduleHash, unsigned int FE, float Q) const
Definition: PixelChargeCalibCondData.cxx:163
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
PixelDigitization
Definition: PixelDigitizationUtilities.cxx:16
FEI4SimTool::~FEI4SimTool
virtual ~FEI4SimTool()
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
SiHelper::disabled
static void disabled(SiChargedDiode &chDiode, bool flag, bool mask=false)
Definition: SiHelper.h:93
PixelID::wafer_id
Identifier wafer_id(int barrel_ec, int layer_disk, int phi_module, int eta_module) const
For a single crystal.
Definition: PixelID.h:364
InDetDD::SolidStateDetectorElementBase::getIdHelper
const AtlasDetectorID * getIdHelper() const
Returns the id helper (inline)
PixelDigitization::getG4Time
double getG4Time(const SiTotalCharge &totalCharge)
Definition: PixelNoiseFunctions.cxx:205
SiChargedDiode::charge
double charge() const
Definition: SiChargedDiode.h:115
PixelDigitization::randomThreshold
double randomThreshold(const PixelChargeCalib::Thresholds &t, CLHEP::HepRandomEngine *pEngine)
Definition: PixelDigitizationUtilities.cxx:105
FEI4SimTool.h
SiTotalCharge::fromTrack
bool fromTrack() const
Definition: SiTotalCharge.cxx:49
FrontEndSimTool::initialize
virtual StatusCode initialize() override
Definition: FrontEndSimTool.cxx:13
SiChargedDiode::diode
const InDetDD::SiCellId & diode() const
Definition: SiChargedDiode.h:97
FEI4SimTool::process
virtual void process(SiChargedDiodeCollection &chargedDiodes, PixelRDO_Collection &rdoCollection, CLHEP::HepRandomEngine *rndmEngine) const
Definition: FEI4SimTool.cxx:57
InDetDD::SolidStateDetectorElementBase::identifierFromCellId
virtual Identifier identifierFromCellId(const SiCellId &cellId) const =0
Identifier <-> SiCellId (ie strip number or pixel eta_index,phi_index) Identifier from SiCellId (ie s...
FrontEndSimTool::m_doNoise
Gaudi::Property< bool > m_doNoise
Definition: FrontEndSimTool.h:72
SiChargedDiodeCollection::getId
Identifier getId(const InDetDD::SiCellId &id) const
Definition: SiChargedDiodeCollection.h:144
SiChargedDiode::totalCharge
const SiTotalCharge & totalCharge() const
Definition: SiChargedDiode.h:107
InDetDD::SiCellId::etaIndex
int etaIndex() const
Get eta index.
Definition: SiCellId.h:114
PixelID::wafer_hash
IdentifierHash wafer_hash(Identifier wafer_id) const
wafer hash from id
Definition: PixelID.h:387
FrontEndSimTool::m_bunchSpace
static constexpr double m_bunchSpace
Definition: FrontEndSimTool.h:50
Base_Fragment.recorded
list recorded
if USE_PDG_VALUES = True, load PDG value of sin2thetaW and particle masses/widths from parameter dict...
Definition: GeneratorFilters/share/common/Base_Fragment.py:55
SiChargedDiodeCollection
Definition: SiChargedDiodeCollection.h:109
PixelRDO_Collection.h
FrontEndSimTool
Definition: FrontEndSimTool.h:31
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
PixelChargeCalibCondData
Definition: PixelChargeCalibCondData.h:24
SiHelper::belowThreshold
static void belowThreshold(SiChargedDiode &chDiode, bool flag, bool mask=false)
Definition: SiHelper.h:84
FrontEndSimTool::m_numberOfBcid
int m_numberOfBcid
Definition: FrontEndSimTool.h:51
master.flag
bool flag
Definition: master.py:29
Pixel1RawData.h
InDetRawDataCollection
Definition: InDetRawDataCollection.h:31
test_pyathena.parent
parent
Definition: test_pyathena.py:15
FrontEndSimTool::m_pixelReadout
ServiceHandle< InDetDD::IPixelReadoutManager > m_pixelReadout
Definition: FrontEndSimTool.h:59
SiHelper::SetBunch
static void SetBunch(SiChargedDiode &chDiode, int bunch, MsgStream *log=nullptr)
Definition: SiHelper.h:129
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
FrontEndSimTool::m_BarrelEC
Gaudi::Property< int > m_BarrelEC
Definition: FrontEndSimTool.h:68
SiChargedDiode::flag
int flag() const
Definition: SiChargedDiode.h:102
PixelID::layer_disk
int layer_disk(const Identifier &id) const
Definition: PixelID.h:626
SiHelper::isMaskOut
static bool isMaskOut(SiChargedDiode &chDiode)
Definition: SiHelper.h:171
python.EventInfoMgtInit.release
release
Definition: EventInfoMgtInit.py:24
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
IdentifierHash.h
threshold
Definition: chainparser.cxx:74
charge
double charge(const T &p)
Definition: AtlasPID.h:931
FEI4SimTool::finalize
virtual StatusCode finalize()
Definition: FEI4SimTool.cxx:52
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
InDetDD::PixelReadoutTechnology::FEI4
@ FEI4
InDetDD::PixelModuleDesign::getReadoutTechnology
PixelReadoutTechnology getReadoutTechnology() const
Definition: PixelModuleDesign.h:386
query_example.col
col
Definition: query_example.py:7
PixelDigitization::crossTalk
void crossTalk(double crossTalk, SiChargedDiodeCollection &chargedDiodes)
Definition: PixelNoiseFunctions.cxx:27
InDetDD::PixelModuleDesign::rowsPerCircuit
int rowsPerCircuit() const
Number of cell rows per circuit:
Definition: PixelModuleDesign.h:335
PixelModuleDesign.h
InDetDD::PixelDiodeType::NONE
@ NONE
FrontEndSimTool::m_timeOffset
double m_timeOffset
Definition: FrontEndSimTool.h:52
PixelChargeCalibCondData::getFEI4OverflowToT
constexpr int getFEI4OverflowToT() const
Definition: PixelChargeCalibCondData.h:112
PixelDigitizationUtilities.h
SiChargedDiodeOrderedIterator
SiChargedDiodeOrderedSet::iterator SiChargedDiodeOrderedIterator
Definition: SiChargedDiodeCollection.h:107
FrontEndSimTool::m_chargeDataKey
SG::ReadCondHandleKey< PixelChargeCalibCondData > m_chargeDataKey
Definition: FrontEndSimTool.h:64
SiChargedDiodeCollection::orderedBegin
SiChargedDiodeOrderedIterator orderedBegin()
Definition: SiChargedDiodeCollection.h:258
InDetDD::SiReadoutCellId
Definition: SiReadoutCellId.h:42
PixelDigitization::randomNoise
void randomNoise(SiChargedDiodeCollection &chargedDiodes, const PixelModuleData *moduleData, int nBcid, const PixelChargeCalibCondData *chargeCalibData, CLHEP::HepRandomEngine *rndmEngine, InDetDD::IPixelReadoutManager *pixelReadout)
Definition: PixelNoiseFunctions.cxx:75
PixelID
Definition: PixelID.h:67
InDetDD::PixelModuleDesign::columnsPerCircuit
int columnsPerCircuit() const
Number of cell columns per circuit:
Definition: PixelModuleDesign.h:330
FrontEndSimTool::m_pixelConditionsTool
ToolHandle< IInDetConditionsTool > m_pixelConditionsTool
Definition: FrontEndSimTool.h:55
PixelDigitization::randomDisable
void randomDisable(SiChargedDiodeCollection &chargedDiodes, const PixelModuleData *moduleData, CLHEP::HepRandomEngine *rndmEngine)
Definition: PixelNoiseFunctions.cxx:163
InDetDD::SolidStateDetectorElementBase::identify
virtual Identifier identify() const override final
identifier of this detector element (inline)
PixelDigitization::thermalNoise
void thermalNoise(double thermalNoise, SiChargedDiodeCollection &chargedDiodes, CLHEP::HepRandomEngine *rndmEngine)
Definition: PixelNoiseFunctions.cxx:63
SiChargedDiodeCollection.h
SiChargedDiodeCollection::identify
virtual Identifier identify() const override final
Definition: SiChargedDiodeCollection.h:230
Identifier
Definition: IdentifierFieldParser.cxx:14