ATLAS Offline Software
PixelNoiseFunctions.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 "PixelNoiseFunctions.h"
6 
7 #include "CLHEP/Random/RandomEngine.h"
8 #include "CLHEP/Random/RandGaussZiggurat.h"
9 #include "CLHEP/Random/RandFlat.h"
10 #include "CLHEP/Random/RandPoisson.h"
11 
14 
20 #include <limits>
21 
22 
23 namespace PixelDigitization{
24  void
25  crossTalk(double crossTalk, SiChargedDiodeCollection& chargedDiodes){
26  const InDetDD::PixelModuleDesign* p_design =
27  static_cast<const InDetDD::PixelModuleDesign*>(&(chargedDiodes.element())->design());
28  SiChargedDiodeMap oldChargedDiodes = chargedDiodes.chargedDiodes();
29 
30  for (SiChargedDiodeIterator i_chargedDiode = oldChargedDiodes.begin(); i_chargedDiode != oldChargedDiodes.end();
31  ++i_chargedDiode) {
32  InDetDD::SiCellId diode = (*i_chargedDiode).second.diode();
33  std::vector<InDetDD::SiCellId> neighbours;
34  p_design->neighboursOfCell(diode, neighbours);
35  for (std::vector<InDetDD::SiCellId>::const_iterator p_neighbour = neighbours.begin();
36  p_neighbour != neighbours.end(); ++p_neighbour) {
37  const double intersection = p_design->intersectionLength(diode, *p_neighbour);
38  // add cross talk only if the intersection is non-zero
39  // if the original pixel is at (col,row) then the intersection length is
40  // (col+-1, row+-1) : 0 -> diagonal
41  // (col , row+-1) : 0.4 mm (or 0.6 if long pixel) pixel width = 400um or 600um
42  // (col+-1, row ) : 0.05 mm , pixel height = 50um
43  // intersection length is just the length of the contact surface between the two pixels
44  if (intersection > 0) {
45  // create a new charge:
46  // Q(new) = Q*L*X
47  // Q = charge of source pixel
48  // L = intersection length [mm]
49  // X = crosstalk factor [mm-1]
50  const SiChargedDiode& siCharge = (*i_chargedDiode).second;
52  siCharge.totalCharge().time(), SiCharge::diodeX_Talk, siCharge.totalCharge().particleLink());
53  chargedDiodes.add(*p_neighbour, charge);
54  }
55  }
56  }
57  return;
58  }
59 
60  void
62  CLHEP::HepRandomEngine* rndmEngine) {
63  for (SiChargedDiodeOrderedIterator i_chargedDiode = chargedDiodes.orderedBegin();
64  i_chargedDiode != chargedDiodes.orderedEnd(); ++i_chargedDiode) {
65  SiCharge charge(thermalNoise * CLHEP::RandGaussZiggurat::shoot(rndmEngine), 0, SiCharge::noise);
66  (*i_chargedDiode)->add(charge);
67  }
68  return;
69  }
70 
71 
72  void
73  randomNoise(SiChargedDiodeCollection& chargedDiodes, const PixelModuleData *moduleData,
74  int nBcid,
75  const PixelChargeCalibCondData *chargeCalibData, CLHEP::HepRandomEngine* rndmEngine,
76  InDetDD::IPixelReadoutManager * pixelReadout) {
77  const InDetDD::PixelModuleDesign* p_design =
78  static_cast<const InDetDD::PixelModuleDesign*>(&(chargedDiodes.element())->design());
79 
80  const PixelID* pixelId = static_cast<const PixelID*>(chargedDiodes.element()->getIdHelper());
81  int barrel_ec = pixelId->barrel_ec(chargedDiodes.element()->identify());
82  int layerIndex = pixelId->layer_disk(chargedDiodes.element()->identify());
83  const double totalNoiseOccupancy = moduleData->getNoiseOccupancy(barrel_ec,layerIndex) * nBcid;
84  //prepare to enter loop
85  const std::vector<float> &noiseShape = moduleData->getNoiseShape(barrel_ec, layerIndex);
86  const auto technology = p_design->getReadoutTechnology();
87  // protection to the overflow ToT, that depends on the sensor technology
88  float overflowToT = std::numeric_limits<float>::max();
89  if (technology == InDetDD::PixelReadoutTechnology::FEI4) {
90  overflowToT = chargeCalibData->getFEI4OverflowToT();
91  } else if (technology == InDetDD::PixelReadoutTechnology::FEI3) {
92  overflowToT = moduleData->getFEI3Latency(barrel_ec, layerIndex);
93  }
94  return randomNoise(chargedDiodes, totalNoiseOccupancy, noiseShape, overflowToT, chargeCalibData, rndmEngine, pixelReadout);
95  }
96 
97  void
98  randomNoise(SiChargedDiodeCollection& chargedDiodes, const double totalNoiseOccupancy, const std::vector<float> &noiseShape, float overflowToT,
99  const PixelChargeCalibCondData *chargeCalibData, CLHEP::HepRandomEngine* rndmEngine, InDetDD::IPixelReadoutManager * pixelReadout){
100  const InDetDD::PixelModuleDesign* p_design =
101  static_cast<const InDetDD::PixelModuleDesign*>(&(chargedDiodes.element())->design());
102 
103  const PixelID* pixelId = static_cast<const PixelID*>(chargedDiodes.element()->getIdHelper());
104  const IdentifierHash moduleHash = pixelId->wafer_hash(chargedDiodes.identify()); // wafer hash
105  const auto nCircuits = p_design->numberOfCircuits();
106  const auto nColumns = p_design->columnsPerCircuit();
107  const auto nRows = p_design->rowsPerCircuit();
108  const auto totalCells = nCircuits * nColumns * nRows;
109  int nNoise = CLHEP::RandPoisson::shoot(rndmEngine, totalCells * totalNoiseOccupancy);
110  //prepare to enter loop
111  const auto technology = p_design->getReadoutTechnology();
112  for (int i = 0; i < nNoise; i++) {
113  int circuit = CLHEP::RandFlat::shootInt(rndmEngine, nCircuits);
114  int column = CLHEP::RandFlat::shootInt(rndmEngine, nColumns);
115  int row = CLHEP::RandFlat::shootInt(rndmEngine, nRows);
116  if (row > 159 && technology == InDetDD::PixelReadoutTechnology::FEI3) {
117  row += 8;
118  } // jump over ganged pixels - rowsPerCircuit == 320 above
119 
120  InDetDD::SiReadoutCellId roCell(row, nColumns * circuit + column);
121  Identifier noisyID = chargedDiodes.element()->identifierFromCellId(roCell);
122 
123  if (roCell.isValid()) {
124  InDetDD::SiCellId diodeNoise = roCell;
125  float x = static_cast<float>(CLHEP::RandFlat::shoot(rndmEngine, 0., 1.)); // returns double
126  size_t bin{};
127  for (size_t j = 1; j < noiseShape.size(); j++) {
128  if (x > noiseShape[j - 1] && x <= noiseShape[j]) {
129  bin = j - 1;
130  break;
131  }
132  }
133  float noiseToTm = bin + 1.5f;
134  float noiseToT = CLHEP::RandGaussZiggurat::shoot(rndmEngine, noiseToTm, 1.f);
135  if (noiseToT < 1.f) { continue; } // throw away unphysical noise
136  noiseToT = std::min(noiseToT, overflowToT);
137  InDetDD::PixelDiodeType type = pixelReadout->getDiodeType(noisyID);
138  if (type == InDetDD::PixelDiodeType::NONE) continue;
139  float chargeShape = chargeCalibData->getCharge(type, moduleHash, circuit, noiseToT);
140  chargedDiodes.add(diodeNoise, SiCharge(chargeShape, 0, SiCharge::noise));
141  }
142  }
143  return;
144  }
145 
146  void
147  randomDisable(SiChargedDiodeCollection& chargedDiodes,const PixelModuleData *moduleData,
148  CLHEP::HepRandomEngine* rndmEngine) {
149  const PixelID* pixelId = static_cast<const PixelID*>(chargedDiodes.element()->getIdHelper());
150  const int barrel_ec = pixelId->barrel_ec(chargedDiodes.element()->identify());
151  const int layerIndex = pixelId->layer_disk(chargedDiodes.element()->identify());
152  const double disableProbability = moduleData->getDisableProbability(barrel_ec, layerIndex);
153  return randomDisable(chargedDiodes, disableProbability, rndmEngine);
154  }
155 
156  void
157  randomDisable(SiChargedDiodeCollection& chargedDiodes, double disableProbability,
158  CLHEP::HepRandomEngine* rndmEngine){
159  for (SiChargedDiodeOrderedIterator i_chargedDiode = chargedDiodes.orderedBegin();
160  i_chargedDiode != chargedDiodes.orderedEnd(); ++i_chargedDiode) {
161  if (CLHEP::RandFlat::shoot(rndmEngine) < disableProbability) {
162  SiHelper::disabled(**i_chargedDiode, true, false);
163  }
164  }
165  return;
166  }
167 
168  double
169  getG4Time(const SiTotalCharge& totalCharge) {
170  // If there is one single charge, return its time:
171  if (totalCharge.chargeComposition().empty()) {
172  return totalCharge.time();
173  }
174  auto p_charge = totalCharge.chargeComposition().begin();
175  int findfirst = 0;
176  SiCharge first = *p_charge;
177  // Look for first charge which is not noise
178  for (; p_charge != totalCharge.chargeComposition().end(); p_charge++) {
179  if (p_charge->processType() != SiCharge::noise) {
180  findfirst = 1;
181  break;
182  }
183  }
184  // if all charges were noise, return the time of the highest charge
185  if (findfirst == 0) {
186  return totalCharge.time();
187  }
188  // look for the earliest charge among the remaining non-noise charges:
189  first = *p_charge;
190  p_charge++;
191  for (; p_charge != totalCharge.chargeComposition().end(); p_charge++) {
192  if (p_charge->time() < first.time() && p_charge->processType() != SiCharge::noise) {
193  first = *p_charge;
194  }
195  }
196  return first.time();
197  }
198 }
query_example.row
row
Definition: query_example.py:24
SiTotalCharge::time
double time() const
Definition: SiTotalCharge.h:151
SiHelper.h
SiChargedDiode
Definition: SiChargedDiode.h:30
PixelNoiseFunctions.h
SiChargedDiodeCollection::element
const InDetDD::SolidStateDetectorElementBase * element() const
Definition: SiChargedDiodeCollection.h:218
InDetDD::PixelModuleDesign
Definition: PixelModuleDesign.h:48
SiTotalCharge.h
PixelID::barrel_ec
int barrel_ec(const Identifier &id) const
Values of different levels (failure returns 0)
Definition: PixelID.h:619
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
InDetDD::PixelModuleDesign::intersectionLength
double intersectionLength(const SiCellId &diode1, const SiCellId &diode2) const
Compute the intersection length of two diodes: return: the intersection length when the two diodes ar...
Definition: PixelModuleDesign.h:373
PixelModuleData
Definition: PixelModuleData.h:22
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
InDetDD::IPixelReadoutManager
Definition: IPixelReadoutManager.h:21
InDetDD::SiCellId::isValid
bool isValid() const
Test if its in a valid state.
Definition: SiCellId.h:136
InDetDD::PixelDiodeType
PixelDiodeType
Definition: PixelReadoutDefinitions.h:25
bin
Definition: BinsDiffFromStripMedian.h:43
DeMoUpdate.column
dictionary column
Definition: DeMoUpdate.py:1110
InDetDD::PixelReadoutTechnology::FEI3
@ FEI3
SiCharge
Definition: SiCharge.h:25
SiChargedDiodeCollection::orderedEnd
SiChargedDiodeOrderedIterator orderedEnd()
Definition: SiChargedDiodeCollection.h:266
SiCharge::diodeX_Talk
@ diodeX_Talk
Definition: SiCharge.h:28
PixelDigitization
Definition: PixelDigitizationUtilities.cxx:16
SiChargedDiodeMap
std::unordered_map< InDetDD::SiCellId, SiChargedDiode, SiChargedDiodeHash, std::equal_to< InDetDD::SiCellId >, SG::ArenaPoolSTLAllocator< std::pair< const InDetDD::SiCellId, SiChargedDiode > > > SiChargedDiodeMap
Definition: SiChargedDiodeCollection.h:66
x
#define x
intersection
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
Definition: compareFlatTrees.cxx:25
SiHelper::disabled
static void disabled(SiChargedDiode &chDiode, bool flag, bool mask=false)
Definition: SiHelper.h:93
InDetDD::SolidStateDetectorElementBase::getIdHelper
const AtlasDetectorID * getIdHelper() const
Returns the id helper (inline)
PixelDigitization::getG4Time
double getG4Time(const SiTotalCharge &totalCharge)
Definition: PixelNoiseFunctions.cxx:169
SiChargedDiodeIterator
SiChargedDiodeMap::iterator SiChargedDiodeIterator
Definition: SiChargedDiodeCollection.h:70
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
SiChargedDiode::charge
double charge() const
Definition: SiChargedDiode.h:115
SiTotalCharge::chargeComposition
const list_t & chargeComposition() const
Definition: SiTotalCharge.h:123
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...
SiChargedDiode::totalCharge
const SiTotalCharge & totalCharge() const
Definition: SiChargedDiode.h:107
InDetDD::IPixelReadoutManager::getDiodeType
virtual PixelDiodeType getDiodeType(Identifier id) const =0
SiCharge::noise
@ noise
Definition: SiCharge.h:28
PixelID::wafer_hash
IdentifierHash wafer_hash(Identifier wafer_id) const
wafer hash from id
Definition: PixelID.h:387
SiChargedDiodeCollection
Definition: SiChargedDiodeCollection.h:109
lumiFormat.i
int i
Definition: lumiFormat.py:85
PixelChargeCalibCondData
Definition: PixelChargeCalibCondData.h:24
InDetDD::PixelModuleDesign::numberOfCircuits
int numberOfCircuits() const
Total number of circuits:
Definition: PixelModuleDesign.h:315
hist_file_dump.f
f
Definition: hist_file_dump.py:135
PixelModuleData::getFEI3Latency
int getFEI3Latency(int barrel_ec, int layer) const
Definition: PixelModuleData.cxx:238
PixelID::layer_disk
int layer_disk(const Identifier &id) const
Definition: PixelID.h:626
charge
double charge(const T &p)
Definition: AtlasPID.h:756
InDetDD::PixelReadoutTechnology::FEI4
@ FEI4
InDetDD::PixelModuleDesign::getReadoutTechnology
PixelReadoutTechnology getReadoutTechnology() const
Definition: PixelModuleDesign.h:386
PixelDigitization::crossTalk
void crossTalk(double crossTalk, SiChargedDiodeCollection &chargedDiodes)
Definition: PixelNoiseFunctions.cxx:25
SiChargedDiodeCollection::add
void add(const InDetDD::SiCellId &diode, const T &charge)
Definition: SiChargedDiodeCollection.h:299
PixelModuleData::getDisableProbability
double getDisableProbability(int barrel_ec, int layer) const
Definition: PixelModuleData.cxx:195
InDetDD::SiCellId
Definition: SiCellId.h:29
SiChargedDiodeCollection::chargedDiodes
SiChargedDiodeMap & chargedDiodes()
Definition: SiChargedDiodeCollection.h:212
SiTotalCharge
Definition: SiTotalCharge.h:24
InDetDD::PixelModuleDesign::rowsPerCircuit
int rowsPerCircuit() const
Number of cell rows per circuit:
Definition: PixelModuleDesign.h:335
PixelModuleDesign.h
PixelModuleData::getNoiseShape
const std::vector< float > & getNoiseShape(int barrel_ec, int layer) const
Definition: PixelModuleData.cxx:217
InDetDD::PixelDiodeType::NONE
@ NONE
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
DeMoScan.first
bool first
Definition: DeMoScan.py:536
PixelChargeCalibCondData::getFEI4OverflowToT
constexpr int getFEI4OverflowToT() const
Definition: PixelChargeCalibCondData.h:106
PixelModuleData::getNoiseOccupancy
double getNoiseOccupancy(int barrel_ec, int layer) const
Definition: PixelModuleData.cxx:173
SiChargedDiodeOrderedIterator
SiChargedDiodeOrderedSet::iterator SiChargedDiodeOrderedIterator
Definition: SiChargedDiodeCollection.h:107
PixelChargeCalibCondData::getCharge
float getCharge(InDetDD::PixelDiodeType type, unsigned int moduleHash, unsigned int FE, float ToT) const
Definition: PixelChargeCalibCondData.cxx:192
InDetDD::PixelModuleDesign::neighboursOfCell
virtual void neighboursOfCell(const SiCellId &cellId, std::vector< SiCellId > &neighbours) const
Get the neighbouring diodes of a given diode: Cell for which the neighbours must be found List of cel...
Definition: PixelModuleDesign.h:367
PixelModuleData.h
Store pixel constant parameters in PixelModuleData.
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
RPDUtils::nRows
unsigned constexpr int nRows
Definition: RPDUtils.h:24
SiTotalCharge::particleLink
const HepMcParticleLink & particleLink() const
Definition: SiTotalCharge.h:160
IdentifierHash
This is a "hash" representation of an Identifier. This encodes a 32 bit index which can be used to lo...
Definition: IdentifierHash.h:25
SiCellId.h
PixelID
Definition: PixelID.h:67
PixelChargeCalibCondData.h
InDetDD::PixelModuleDesign::columnsPerCircuit
int columnsPerCircuit() const
Number of cell columns per circuit:
Definition: PixelModuleDesign.h:330
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)
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