14 #include "CLHEP/Random/RandFlat.h"
15 #include "CLHEP/Random/RandGaussZiggurat.h"
16 #include "CLHEP/Random/RandPoisson.h"
17 #include "CLHEP/Random/RandomEngine.h"
38 ATH_MSG_FATAL(
"AnalogueNoiseOn/m_analogueNoiseOn should be true if NoiseOn/m_NoiseOn is true.");
39 return StatusCode::FAILURE;
59 constexpr
float fC = 6242.2;
80 <<
" is invalid. Abort this job!!!");
81 return StatusCode::FAILURE;
85 <<
" is invalid. Abort this job!!!");
86 return StatusCode::FAILURE;
92 <<
" requires timing information."
94 <<
" (Condensed) does not keep timing information. Abort this job!!!");
95 return StatusCode::FAILURE;
98 return StatusCode::SUCCESS;
105 return StatusCode::SUCCESS;
112 data.m_GainFactor.resize(strips);
115 data.m_Analogue[0].resize(strips);
116 data.m_Analogue[1].resize(strips);
118 data.m_Analogue[0].resize(strips);
119 data.m_Analogue[1].resize(strips);
120 data.m_Analogue[2].resize(strips);
123 return StatusCode::SUCCESS;
133 float A = 4.0f *
W *
W + 1.0f;
134 float x1 = (
A - std::sqrt(
A)) / (2.0
f *
A);
135 float sinfi = std::sqrt(
x1);
136 float cosfi = sqrt(1.0 -
x1);
141 float S1 = std::sqrt((
S + D) * 0.5
f);
142 float S2 = std::sqrt((
S - D) * 0.5
f);
156 switch (moduleType) {
175 ATH_MSG_ERROR(
"moduleType(eta): " << moduleType <<
" unknown, using barrel");
185 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
188 unsigned int flagmask = diode.
flag() & 0xFE;
198 for (;
i < i_end;
i++) {
200 if (
data.m_Analogue[1][
i] <= 0.0) {
201 float g = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0,
S1);
202 float o = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0,
S2);
204 data.m_GainFactor[
i] = 1.0f + (cosfi *
g + sinfi * o);
206 float offset_val = (cosfi * o - sinfi *
g);
208 float noise_val = Noise *
mode;
212 data.m_Analogue[0][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
213 data.m_Analogue[1][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
215 data.m_Analogue[0][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
216 data.m_Analogue[1][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
217 data.m_Analogue[2][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
225 return StatusCode::SUCCESS;
238 std::vector<float> noiseByChipVect(6, 0.0);
245 if (gainByChipVect.empty() or noiseByChipVect.empty()) {
246 ATH_MSG_DEBUG(
"No calibration data in cond DB for module " << moduleId <<
" using JO values");
248 return StatusCode::FAILURE;
250 return StatusCode::SUCCESS;
255 float gainMeanValue =
meanValue(gainByChipVect);
256 if (gainMeanValue < 0.0) {
257 ATH_MSG_DEBUG(
"All chip gain values are 0 for module " << moduleId <<
" using JO values");
259 return StatusCode::FAILURE;
261 return StatusCode::SUCCESS;
265 std::vector<float>
gain(6, 0.0);
266 std::vector<float>
offset(6, 0.0);
267 std::vector<float>
S1(6, 0.0);
268 std::vector<float>
S2(6, 0.0);
269 std::vector<float> sinfi(6, 0.0);
270 std::vector<float> cosfi(6, 0.0);
272 float offsetRMS = 0.0;
274 for (
int i = 0;
i < 6; ++
i) {
276 if (gainByChipVect[
i] > 0.1) {
277 gain[
i] = gainByChipVect[
i] / gainMeanValue;
279 gainRMS = gainRMSByChipVect[
i] / gainMeanValue;
282 gain[
i] = 55.0f / gainMeanValue;
284 gainRMS = 1.3f / gainMeanValue;
288 float W =
m_OGcorr * gainRMS * offsetRMS / (gainRMS * gainRMS - offsetRMS * offsetRMS);
289 float A = 4.0f *
W *
W + 1.0f;
290 float x1 = (
A - std::sqrt(
A)) / (2.0
f *
A);
291 sinfi[
i] = std::sqrt(
x1);
292 cosfi[
i] = std::sqrt(1.0
f -
x1);
294 float S = gainRMS * gainRMS + offsetRMS * offsetRMS;
295 float D = (gainRMS * gainRMS - offsetRMS * offsetRMS) / (cosfi[
i] * cosfi[
i] - sinfi[
i] * sinfi[
i]);
296 S1[
i] = std::sqrt((
S + D) / 2.0
f);
297 S2[
i] = std::sqrt((
S - D) / 2.0
f);
304 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
307 unsigned int flagmask = diode.
flag() & 0xFE;
318 for (;
i < i_end;
i++) {
320 if (
data.m_Analogue[1][
i] <= 0.0) {
323 float g = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0,
S1[chip]);
324 float o = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0,
S2[chip]);
326 data.m_GainFactor[
i] =
gain[chip] + (cosfi[chip] *
g + sinfi[chip] * o);
328 float offset_val =
offset[chip] + (cosfi[chip] * o - sinfi[chip] *
g);
330 float noise_val = noiseByChipVect[chip];
334 data.m_Analogue[0][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
335 data.m_Analogue[1][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
337 data.m_Analogue[0][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
338 data.m_Analogue[1][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
339 data.m_Analogue[2][
i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
347 return StatusCode::SUCCESS;
356 double occupancy = 0.0;
357 double NoiseOccupancy = 0.0;
359 int nNoisyStrips = 0;
365 if (noise_expanded_mode) {
382 switch (moduleType) {
406 ATH_MSG_ERROR(
"moduleType(eta): " << moduleType <<
" unknown, using barrel");
412 int nEmptyStrips = 0;
413 std::vector<int> emptyStrips;
414 emptyStrips.reserve(strip_max);
415 for (
int i = 0;
i < strip_max;
i++) {
416 if (
data.m_StripHitsOnWafer[
i] == 0) {
417 emptyStrips.push_back(
i);
422 if (nEmptyStrips != 0) {
425 occupancy = CLHEP::RandGaussZiggurat::shoot(rndmEngine, NoiseOccupancy, NoiseOccupancy * 0.1);
429 const float fC = 6242.2;
432 nNoisyStrips = CLHEP::RandPoisson::shoot(rndmEngine, strip_max * occupancy *
mode);
435 if (nEmptyStrips < nNoisyStrips) {
436 nNoisyStrips = nEmptyStrips;
440 for (
int i = 0;
i < nNoisyStrips;
i++) {
441 int index = CLHEP::RandFlat::shootInt(rndmEngine, nEmptyStrips -
i);
444 emptyStrips.erase(emptyStrips.begin()+
index);
446 ATH_MSG_ERROR(
index <<
"-th empty strip, strip " <<
strip <<
" should be empty but is not empty! Something is wrong!");
450 if (noise_expanded_mode) {
451 int noise_tbin = CLHEP::RandFlat::shootInt(rndmEngine, 3);
453 if (noise_tbin == 0) {
457 ATH_MSG_ERROR(
"Can't add noise hit diode to collection (1)");
461 ATH_MSG_ERROR(
"Can't add noise hit diode to collection (2)");
467 return StatusCode::SUCCESS;
474 const int n_chips = 6;
475 const int chipStripmax = strip_max / n_chips;
476 std::vector<float> NOByChipVect(n_chips, 0.0);
477 std::vector<float> ENCByChipVect(n_chips, 0.0);
478 std::vector<int> nNoisyStrips(n_chips, 0);
484 if (noise_expanded_mode) {
493 if (NOByChipVect.empty()) {
494 ATH_MSG_DEBUG(
"No calibration data in cond DB for module " << moduleId <<
" using JO values");
495 if (StatusCode::SUCCESS !=
randomNoise(collection, moduleId, rndmEngine,
data,strip_max)) {
496 return StatusCode::FAILURE;
498 return StatusCode::SUCCESS;
501 for (
int i = 0;
i < n_chips;
i++) {
507 constexpr
float fC = 6242.2;
511 nNoisyStrips[
i] = CLHEP::RandPoisson::shoot(rndmEngine, chipStripmax * NOByChipVect[
i] *
mode);
516 for (
int chip_index = 0; chip_index < n_chips; ++chip_index) {
517 int chip_strip_offset = chipStripmax * chip_index;
520 int nEmptyStripsOnChip = 0;
521 std::vector<int> emptyStripsOnChip;
522 emptyStripsOnChip.reserve(chipStripmax);
523 for (
int i = 0;
i < chipStripmax;
i++) {
524 if (
data.m_StripHitsOnWafer[
i + chip_strip_offset] == 0) {
525 emptyStripsOnChip.push_back(
i);
526 ++nEmptyStripsOnChip;
531 if (nEmptyStripsOnChip != 0) {
533 if (nEmptyStripsOnChip < nNoisyStrips[chip_index]) {
534 nNoisyStrips[chip_index] = nEmptyStripsOnChip;
538 for (
int i = 0;
i < nNoisyStrips[chip_index];
i++) {
539 int index = CLHEP::RandFlat::shootInt(rndmEngine, nEmptyStripsOnChip -
i);
540 int strip_on_chip = emptyStripsOnChip.at(
index);
541 emptyStripsOnChip.erase(emptyStripsOnChip.begin()+
index);
542 int strip = strip_on_chip + chip_strip_offset;
544 ATH_MSG_ERROR(
index <<
"-th empty strip, strip " <<
strip <<
" should be empty but is not empty! Something is wrong!");
548 if (noise_expanded_mode) {
550 int noise_tbin = CLHEP::RandFlat::shootInt(rndmEngine, 3);
552 if (noise_tbin == 0) {
556 ATH_MSG_ERROR(
"Can't add noise hit diode to collection (3)");
560 ATH_MSG_ERROR(
"Can't add noise hit diode to collection (4)");
567 return StatusCode::SUCCESS;
584 const int strip_max = p_design->
cells();
592 data.m_StripHitsOnWafer.assign(strip_max, 0);
603 if (not collection.
empty()) {
630 if (StatusCode::SUCCESS !=
randomNoise(collection, moduleId,
side, rndmEngine,
data, strip_max)) {
634 if (StatusCode::SUCCESS !=
randomNoise(collection, moduleId, rndmEngine,
data,strip_max)) {
661 std::vector<float>
response(bin_max);
665 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
668 unsigned int flagmask = diode.
flag() & 0xFE;
681 for (
short bin = 0;
bin < bin_max; ++
bin) {
686 for (
short bin = 0;
bin < bin_max; ++
bin) {
687 if (
strip + 1 < strip_max) {
697 for (
short bin = 0;
bin < bin_max; ++
bin) {
702 for (
short bin = 0;
bin < bin_max; ++
bin) {
703 if (
strip + 1 < strip_max) {
718 return StatusCode::SUCCESS;
729 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
739 }
else if (((0x10 & diode.
flag()) == 0x10) or ((0x4 & diode.
flag()) == 0x4)) {
747 int have_hit_bin = 0;
757 if (((0x10 & diode.
flag()) == 0x10) || ((0x4 & diode.
flag()) == 0x4)) {
761 if (have_hit_bin == 2 or have_hit_bin == 3 or have_hit_bin == 6 or have_hit_bin == 7) {
769 if (have_hit_bin == 2 or have_hit_bin == 3) {
777 if (have_hit_bin == 0) {
793 return StatusCode::SUCCESS;
808 if (
data.m_StripHitsOnWafer[
strip] != 0) {
820 ATH_MSG_ERROR(
"Can't add noise hit diode to collection (5)");
824 int have_hit_bin = 0;
835 if (have_hit_bin == 2 or have_hit_bin == 3 or have_hit_bin == 6 or have_hit_bin == 7) {
838 ATH_MSG_ERROR(
"Can't add noise hit diode to collection (6)");
844 if (have_hit_bin == 2 or have_hit_bin == 3) {
847 ATH_MSG_ERROR(
"Can't add noise hit diode to collection (7)");
853 if (have_hit_bin == 0) {
859 ATH_MSG_ERROR(
"Can't add noise hit diode to collection (8)");
863 ATH_MSG_ERROR(
"Can't add noise hit diode to collection (9)");
872 return StatusCode::SUCCESS;
888 if (
data.m_StripHitsOnWafer[
strip] > 0) {
891 int clusterFirstStrip =
strip;
899 int lastStrip1DInRow = 0;
900 for (
int i = 0;
i <
row + 1; ++
i) {
904 while (
strip < lastStrip1DInRow-1 and
data.m_StripHitsOnWafer[
strip +1] > 0) {
907 int clusterLastStrip =
strip;
909 clusterSize = (clusterLastStrip - clusterFirstStrip) + 1;
910 hitStrip =
SiCellId(clusterFirstStrip);
915 for (
int i = clusterFirstStrip+1;
i <= clusterLastStrip; ++
i) {
920 PreviousHitDiode = &HitDiode2;
924 }
while (
strip < strip_max);
930 if (
data.m_StripHitsOnWafer[
strip] > 0) {
936 for (
int newStrip=
strip+1; newStrip<strip_max; newStrip++) {
937 if (not (
data.m_StripHitsOnWafer[newStrip]>0))
break;
943 previousHitDiode = &newHitDiode;
951 ", HitInfo(1=real, 2=crosstalk, 3=noise): " <<
955 strip += clusterSize;
956 }
while (
strip < strip_max);
966 return StatusCode::SUCCESS;
972 collection.
add(ndiode, noiseCharge);
976 if (NoiseDiode ==
nullptr) {
977 return StatusCode::FAILURE;
980 return StatusCode::SUCCESS;
984 float mean_value = 0.0;
986 const unsigned int vec_size = calibDataVect.size();
989 if (calibDataVect[
i] > 0.1) {
990 mean_value += calibDataVect[
i];
998 return mean_value / nData;