ATLAS Offline Software
FEI4SimTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3  */
4 
5 #include "FEI4SimTool.h"
7 
8 #include "PixelConditionsData/ChargeCalibParameters.h" //for Thresholds
12 
16 //
17 #include "CLHEP/Random/RandGaussZiggurat.h"
18 #include "CLHEP/Random/RandFlat.h"
19 #include "PixelNoiseFunctions.h"
20 #include <array>
21 #include <algorithm>
22 
23 
24 using namespace PixelDigitization;
25 
26 
27 
28 namespace{
29  double
30  getSigma(int tot){
31  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};
32  return sigmas.at(tot);
33  }
34 
35 }
36 
37 
38 
39 FEI4SimTool::FEI4SimTool(const std::string& type, const std::string& name, const IInterface* parent) :
41 }
42 
43 FEI4SimTool::~FEI4SimTool() = default;
44 
47  ATH_MSG_DEBUG("FEI4SimTool::initialize()");
49 
50  return StatusCode::SUCCESS;
51 }
52 
54  ATH_MSG_DEBUG("FEI4SimTool::finalize()");
55  return StatusCode::SUCCESS;
56 }
57 
59  CLHEP::HepRandomEngine* rndmEngine) {
60  const InDetDD::PixelModuleDesign* p_design =
61  static_cast<const InDetDD::PixelModuleDesign*>(&(chargedDiodes.element())->design());
62 
64  return;
65  }
66 
67  const PixelID* pixelId = static_cast<const PixelID*>(chargedDiodes.element()->getIdHelper());
68  const IdentifierHash moduleHash = pixelId->wafer_hash(chargedDiodes.identify()); // wafer hash
69  Identifier moduleID = pixelId->wafer_id(chargedDiodes.element()->identify());
70 
71  int barrel_ec = pixelId->barrel_ec(chargedDiodes.element()->identify());
72  int layerIndex = pixelId->layer_disk(chargedDiodes.element()->identify());
73 
74  if (std::abs(barrel_ec) != m_BarrelEC) {
75  return;
76  }
77 
78  const EventContext& ctx{Gaudi::Hive::currentContext()};
80  const PixelModuleData *moduleData = *moduleDataHandle;
82  const PixelChargeCalibCondData *calibData = *calibDataHandle;
83 
84  int maxFEI4SmallHit = 2;
85  int overflowToT = calibData->getFEI4OverflowToT();
86 
87  std::vector<std::unique_ptr<Pixel1RawData>> p_rdo_small_fei4;
88  int nSmallHitsFEI4 = 0;
89  std::vector<int> row, col;
90  const int maxRow = p_design->rowsPerCircuit();
91  const int maxCol = p_design->columnsPerCircuit();
92  std::vector<std::vector<int> > FEI4Map(maxRow + 16, std::vector<int>(maxCol + 16));
93 
94  // Add cross-talk
95  crossTalk(moduleData->getCrossTalk(barrel_ec, layerIndex), chargedDiodes);
96 
97  if (m_doNoise) {
98  // Add thermal noise
99  thermalNoise(m_thermalNoise, chargedDiodes, rndmEngine);
100 
101  // Add random noise
102  randomNoise(chargedDiodes, moduleData, m_numberOfBcid, calibData, rndmEngine, m_pixelReadout.get());
103  }
104 
105  // Add random diabled pixels
106  randomDisable(chargedDiodes, moduleData, rndmEngine); // FIXME How should we handle disabling pixels in Overlay jobs?
107 
108  for (SiChargedDiodeOrderedIterator i_chargedDiode = chargedDiodes.orderedBegin();
109  i_chargedDiode != chargedDiodes.orderedEnd(); ++i_chargedDiode) {
110  SiChargedDiode& diode = **i_chargedDiode;
111 
112  Identifier diodeID = chargedDiodes.getId(diode.diode());
113  double charge = diode.charge();
114 
115  // charge scaling function applied. (Reference: ATL-COM-INDET-2018-052)
116 
117  double corrQ = 1.11 *
118  (1.0 - (-7.09 * 1000.0) / (23.72 * 1000.0 + charge) + (-0.22 * 1000.0) /
119  (-0.42 * 1000.0 + charge));
120  if (corrQ < 1.0) {
121  corrQ = 1.0;
122  }
123  charge *= 1.0 / corrQ;
124 
125  //could scale if necessary
126 
127  unsigned int FE = m_pixelReadout->getFE(diodeID, moduleID);
128  InDetDD::PixelDiodeType type = m_pixelReadout->getDiodeType(diodeID);
129  if ((FE == InDetDD::invalidFrontEnd) or (type == InDetDD::PixelDiodeType::NONE)) continue;//invalid frontend
130 
131  // Apply analog threshold, timing simulation
132  const auto & thresholds = calibData->getThresholds(type, moduleHash, FE);
133  double threshold = PixelDigitization::randomThreshold(thresholds, rndmEngine);
134  // This noise check is unaffected by digitizationFlags.doInDetNoise in
135  // 21.0 - see PixelCellDiscriminator.cxx in that branch
136 
137  if (charge > threshold) {
138  int bunchSim;
139  if (diode.totalCharge().fromTrack()) {
140  bunchSim =
141  static_cast<int>(std::floor((getG4Time(diode.totalCharge()) +
143  } else {
144  bunchSim = CLHEP::RandFlat::shootInt(rndmEngine, m_numberOfBcid);
145  }
146 
147  if (bunchSim < 0 || bunchSim > m_numberOfBcid) {
148  SiHelper::belowThreshold(diode, true, true);
149  } else {
150  SiHelper::SetBunch(diode, bunchSim);
151  }
152  } else {
153  SiHelper::belowThreshold(diode, true, true);
154  }
155 
156  // charge to ToT conversion
157  double tot = calibData->getToT(type, moduleHash, FE, charge);
158  double totsig = calibData->getTotRes(moduleHash, FE, tot);
159  int nToT = static_cast<int>(CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot, totsig));
160 
161  // This is for new IBL calibration, since above method (stat_cast) is not effective.
162  if (totsig==0.0) {
163  double totIBLsig = getSigma(nToT);
164  if (totIBLsig) {
165  if (CLHEP::RandFlat::shoot(rndmEngine,0.0,1.0)<std::exp(-0.5/totIBLsig/totIBLsig)) {
166  if (CLHEP::RandFlat::shoot(rndmEngine,0.0,1.0)<0.5) { nToT--; }
167  else { nToT++; }
168  }
169  }
170  }
171 
172 
173 
174  // FEI4 HitDiscConfig
175  if (nToT == 2 && maxFEI4SmallHit == 2) {
176  nToT = 1;
177  }
178 
179  nToT=std::clamp(nToT, 1, overflowToT);
180 
181  if (nToT <= moduleData->getToTThreshold(barrel_ec, layerIndex)) {
182  SiHelper::belowThreshold(diode, true, true);
183  }
184 
185  // Filter events
186  if (SiHelper::isMaskOut(diode)) {
187  continue;
188  }
189  if (SiHelper::isDisabled(diode)) {
190  continue;
191  }
192 
193  if (!m_pixelConditionsTool->isActive(moduleHash, diodeID, ctx)) {
194  SiHelper::disabled(diode, true, true);
195  continue;
196  }
197 
198  int flag = diode.flag();
199  int bunch = (flag >> 8) & 0xff;
200 
201  InDetDD::SiReadoutCellId cellId = diode.getReadoutCell();
202  const Identifier id_readout = chargedDiodes.element()->identifierFromCellId(cellId);
203 
204  int iirow = cellId.phiIndex();
205  int iicol = cellId.etaIndex();
206  if (iicol >= maxCol) {
207  iicol = iicol - maxCol;
208  } // FEI4 copy mechanism works per FE.
209 
210  // Front-End simulation
211  if (bunch >= 0 && bunch < m_numberOfBcid) {
212  auto p_rdo = std::make_unique<Pixel1RawData>(id_readout, nToT, bunch, 0, bunch);
213  if (nToT > maxFEI4SmallHit) {
214  rdoCollection.push_back(p_rdo.release());
215  FEI4Map[iirow][iicol] = 2; //Flag for "big hits"
216  } else {
217  p_rdo_small_fei4.push_back(std::move(p_rdo));
218  row.push_back(iirow);
219  col.push_back(iicol);
220  FEI4Map[iirow][iicol] = 1; //Flag for low hits
221  nSmallHitsFEI4++;
222  }
223  }
224  }
225 
226  // Copy mechanism for IBL small hits:
227  if (nSmallHitsFEI4 > 0) {
228  bool recorded = false;
229 
230  //First case: Record small hits which are in the same Pixel Digital Region than a big hit:
231  for (int ismall = 0; ismall < nSmallHitsFEI4; ismall++) {
232  int rowPDR = row[ismall] / 2;
233  int colPDR = col[ismall] / 2;
234  for (int rowBigHit = 2 * rowPDR; rowBigHit != 2 * rowPDR + 2 && rowBigHit < maxRow; ++rowBigHit) {
235  for (int colBigHit = 2 * colPDR; colBigHit != 2 * colPDR + 2 && colBigHit < maxCol; ++colBigHit) {
237  "rowBig = " << rowBigHit << " colBig = " << colBigHit << " Map Content = " <<
238  FEI4Map[rowBigHit][colBigHit]);
239  if (FEI4Map[rowBigHit][colBigHit] == 2 && !recorded) {
240  rdoCollection.push_back(p_rdo_small_fei4[ismall].release());
241  recorded = true;
242  }
243  }
244  }
245 
246  // Second case: Record small hits which are phi-neighbours with a big hit:
247  if (!recorded && row[ismall] < maxRow - 1) {
248  if (FEI4Map[row[ismall] + 1][col[ismall]] == 2) {
249  rdoCollection.push_back(p_rdo_small_fei4[ismall].release());
250  recorded = true;
251  }
252  }
253  if (!recorded && row[ismall] != 0) {
254  if (FEI4Map[row[ismall] - 1][col[ismall]] == 2) {
255  rdoCollection.push_back(p_rdo_small_fei4[ismall].release());
256  recorded = true;
257  }
258  }
259  }
260  }
261  }
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:45
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:44
SiChargedDiode::getReadoutCell
const InDetDD::SiReadoutCellId & getReadoutCell() const
Definition: SiChargedDiode.h:111
InDetDD::PixelDiodeType
PixelDiodeType
Definition: PixelReadoutDefinitions.h:25
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()
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:169
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
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:228
IdentifierHash.h
threshold
Definition: chainparser.cxx:74
charge
double charge(const T &p)
Definition: AtlasPID.h:756
FEI4SimTool::finalize
virtual StatusCode finalize()
Definition: FEI4SimTool.cxx:53
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:25
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
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
PixelChargeCalibCondData::getFEI4OverflowToT
constexpr int getFEI4OverflowToT() const
Definition: PixelChargeCalibCondData.h:106
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:73
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:147
InDetDD::SolidStateDetectorElementBase::identify
virtual Identifier identify() const override final
identifier of this detector element (inline)
FEI4SimTool::process
virtual void process(SiChargedDiodeCollection &chargedDiodes, PixelRDO_Collection &rdoCollection, CLHEP::HepRandomEngine *rndmEngine)
Definition: FEI4SimTool.cxx:58
PixelDigitization::thermalNoise
void thermalNoise(double thermalNoise, SiChargedDiodeCollection &chargedDiodes, CLHEP::HepRandomEngine *rndmEngine)
Definition: PixelNoiseFunctions.cxx:61
SiChargedDiodeCollection.h
SiChargedDiodeCollection::identify
virtual Identifier identify() const override final
Definition: SiChargedDiodeCollection.h:230
Identifier
Definition: IdentifierFieldParser.cxx:14