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