14 #include "GaudiKernel/ServiceHandle.h"
15 #include "GaudiKernel/ToolHandle.h"
17 #include "CLHEP/Random/RandFlat.h"
19 #include "CLHEP/Units/SystemOfUnits.h"
38 CLHEP::HepRandomEngine* noiseRndmEngine,
39 CLHEP::HepRandomEngine* elecNoiseRndmEngine,
40 CLHEP::HepRandomEngine* elecProcRndmEngine,
41 CLHEP::HepRandomEngine* elecNoiseResetRndmEngine,
47 ToolHandle<ITRT_StrawStatusSummaryTool> sumTool
52 m_pDigConditions(digcond),
53 m_pElectronicsProcessing(ep),
54 m_pElectronicsNoise(electronicsnoise),
56 m_digitPoolLength(5000),
57 m_digitPoolLength_nextaccessindex(0),
58 m_UseGasMix(UseGasMix),
59 m_sumTool(std::move(sumTool))
70 CLHEP::HepRandomEngine* elecNoiseRndmEngine,
71 CLHEP::HepRandomEngine* elecProcRndmEngine) {
98 std::vector<float> maxLTOverNoiseAmp;
101 std::stable_sort( maxLTOverNoiseAmp.begin(), maxLTOverNoiseAmp.end() );
102 reverse( maxLTOverNoiseAmp.begin(), maxLTOverNoiseAmp.end() );
108 if ( relfluct > 0. ) {
109 std::vector<float> nl_given_LT2Amp;
110 float min_lt2amp, max_lt2amp;
112 nl_given_LT2Amp, min_lt2amp, max_lt2amp);
113 float new_min_lt2amp, new_max_lt2amp;
115 min_lt2amp, max_lt2amp,
117 new_min_lt2amp, new_max_lt2amp,
118 static_cast<unsigned int>(0.1*nl_given_LT2Amp.size()));
129 unsigned long nstrawsBa_Xe(0), nstrawsEC_Xe(0);
130 unsigned long nstrawsBa_Kr(0), nstrawsEC_Kr(0);
131 unsigned long nstrawsBa_Ar(0), nstrawsEC_Ar(0);
132 double sumBa_Xe(0.), sumEC_Xe(0.);
133 double sumBa_Kr(0.), sumEC_Kr(0.);
134 double sumBa_Ar(0.), sumEC_Ar(0.);
136 float noiselevel(0.), noiseamp(0.);
143 const bool isBarrel(!(hitid & 0x00200000));
146 float lt =
useLookupTable(noiselevel, maxLTOverNoiseAmp, 0., 1.) * noiseamp;
148 if (strawGasType==0) {
149 if (
isBarrel ) { ++nstrawsBa_Xe; sumBa_Xe += lt; }
150 else { ++nstrawsEC_Xe; sumEC_Xe += lt; }
152 else if (strawGasType==1) {
153 if (
isBarrel ) { ++nstrawsBa_Kr; sumBa_Kr += lt; }
154 else { ++nstrawsEC_Kr; sumEC_Kr += lt; }
156 else if (strawGasType==2) {
157 if (
isBarrel ) { ++nstrawsBa_Ar; sumBa_Ar += lt; }
158 else { ++nstrawsEC_Ar; sumEC_Ar += lt; }
164 double kBa_Xe(0.), kEC_Xe(0.);
165 double kBa_Kr(0.), kEC_Kr(0.);
166 double kBa_Ar(0.), kEC_Ar(0.);
178 std::vector<float> actual_LTs, actual_noiseamps;
179 std::vector<int> strawTypes;
182 actual_LTs.reserve(nstraws);
183 actual_noiseamps.reserve(nstraws);
186 float actualLT, actualNA;
190 double sumLT_Ar(0.), sumLTsq_Ar(0.), sumNA_Ar(0.), sumNAsq_Ar(0.);
191 double sumLT_Xe(0.), sumLTsq_Xe(0.), sumNA_Xe(0.), sumNAsq_Xe(0.);
192 double sumLT_Kr(0.), sumLTsq_Kr(0.), sumNA_Kr(0.), sumNAsq_Kr(0.);
199 const bool isBarrel(!(hitid & 0x00200000));
200 if (strawGasType==0) { actualNA = noiseamp*(
isBarrel ? kBa_Xe : kEC_Xe ); }
201 else if (strawGasType==1) { actualNA = noiseamp*(
isBarrel ? kBa_Kr : kEC_Kr ); }
202 else if (strawGasType==2) { actualNA = noiseamp*(
isBarrel ? kBa_Ar : kEC_Ar ); }
203 else { actualNA = 0.0; }
205 actualLT =
useLookupTable(noiselevel, maxLTOverNoiseAmp, 0., 1.)*actualNA;
207 if (strawGasType==0) {
208 sumNA_Xe += actualNA; sumNAsq_Xe += actualNA*actualNA;
209 sumLT_Xe += actualLT; sumLTsq_Xe += actualLT*actualLT;
211 else if (strawGasType==1) {
212 sumNA_Kr += actualNA; sumNAsq_Kr += actualNA*actualNA;
213 sumLT_Kr += actualLT; sumLTsq_Kr += actualLT*actualLT;
215 else if (strawGasType==2) {
216 sumNA_Ar += actualNA; sumNAsq_Ar += actualNA*actualNA;
217 sumLT_Ar += actualLT; sumLTsq_Ar += actualLT*actualLT;
223 actual_LTs.push_back(actualLT);
224 actual_noiseamps.push_back(actualNA);
225 strawTypes.push_back(strawGasType);
233 unsigned long nstraws_Kr = nstrawsBa_Kr + nstrawsEC_Kr;
234 unsigned long nstraws_Xe = nstrawsBa_Xe + nstrawsEC_Xe;
235 unsigned long nstraws_Ar = nstrawsBa_Ar + nstrawsEC_Ar;
239 << sqrt((sumLTsq_Xe/nstraws_Xe)-(sumLT_Xe/nstraws_Xe)*(sumLT_Xe/nstraws_Xe))/
CLHEP::eV <<
" eV");
241 << sqrt((sumNAsq_Xe/nstraws_Xe)-(sumNA_Xe/nstraws_Xe)*(sumNA_Xe/nstraws_Xe))/
CLHEP::eV <<
" eV");
245 << sqrt((sumLTsq_Kr/nstraws_Kr)-(sumLT_Kr/nstraws_Kr)*(sumLT_Kr/nstraws_Kr))/
CLHEP::eV <<
" eV");
247 << sqrt((sumNAsq_Kr/nstraws_Kr)-(sumNA_Kr/nstraws_Kr)*(sumNA_Kr/nstraws_Kr))/
CLHEP::eV <<
" eV");
251 << sqrt((sumLTsq_Ar/nstraws_Ar)-(sumLT_Ar/nstraws_Ar)*(sumLT_Ar/nstraws_Ar))/
CLHEP::eV <<
" eV");
253 << sqrt((sumNAsq_Ar/nstraws_Ar)-(sumNA_Ar/nstraws_Ar)*(sumNA_Ar/nstraws_Ar))/
CLHEP::eV <<
" eV");
262 ProduceNoiseDigitPool( actual_LTs, actual_noiseamps, strawTypes, noiseRndmEngine, elecNoiseRndmEngine, elecProcRndmEngine );
269 const std::vector<float>& noiseamps,
270 const std::vector<int>& strawType,
271 CLHEP::HepRandomEngine* noiseRndmEngine,
272 CLHEP::HepRandomEngine* elecNoiseRndmEngine,
273 CLHEP::HepRandomEngine* elecProcRndmEngine) {
275 unsigned int nstraw = lowthresholds.size();
280 std::vector<TRTElectronicsProcessing::Deposit> deposits;
283 unsigned int nokdigits(0);
284 unsigned int ntries(0);
291 if ( ntries%400==0 ) {
299 istraw = CLHEP::RandFlat::shootInt(noiseRndmEngine, nstraw );
305 lowthresholds.at(istraw),
306 noiseamps.at(istraw),
307 strawType.at(istraw),
313 if (
digit.GetDigit() ) {
325 <<
" (efficiency was " <<
static_cast<double>(
m_digitPool.size())/ntries <<
")");
334 CLHEP::HepRandomEngine* noiseRndmEngine )
337 const std::set<int>::const_iterator sim_hitids_end(sim_hitids.end());
346 if ( sim_hitids.find(hitid) == sim_hitids_end ) {
348 digitVect.emplace_back(hitid,ndigit);
352 digitVect.pop_back(); }
357 const std::set<Identifier>& simhitsIdentifiers,
359 CLHEP::HepRandomEngine* noiseRndmEngine) {
364 std::vector<Identifier> IdsFromChip;
365 std::vector<Identifier> CrossTalkIds;
366 std::vector<Identifier> CrossTalkIdsOtherEnd;
367 std::set<Identifier>::const_iterator simhitsIdentifiers_end = simhitsIdentifiers.end();
368 std::set<Identifier>::const_iterator simhitsIdentifiers_begin = simhitsIdentifiers.begin();
371 for (simhitsIdentifiersIter=simhitsIdentifiers_begin; simhitsIdentifiersIter!=simhitsIdentifiers_end; ++simhitsIdentifiersIter) {
373 TRTStrawNeighbourSvc->getStrawsFromChip(*simhitsIdentifiersIter,IdsFromChip);
374 CrossTalkIds.assign(IdsFromChip.begin(),IdsFromChip.end());
384 if (otherEndID.
get_compact()) { CrossTalkIdsOtherEnd.push_back(otherEndID); }
386 for (
auto & CrossTalkId : CrossTalkIds) {
388 if ( simhitsIdentifiers.find(CrossTalkId) == simhitsIdentifiers_end ) {
390 const int ndigit(
m_digitPool[CLHEP::RandFlat::shootInt(noiseRndmEngine,
392 int barrel_endcap, isneg;
394 case -1: barrel_endcap = 0; isneg = 0;
break;
395 case 1: barrel_endcap = 0; isneg = 1;
break;
397 ATH_MSG_WARNING(
"TRTDigitization::TRTNoise - identifier problems - skipping detector element!!");
408 digitVect.emplace_back(hitid,ndigit);
413 for (
auto &
i : CrossTalkIdsOtherEnd) {
414 if ( simhitsIdentifiers.find(
i) == simhitsIdentifiers_end ) {
419 int barrel_endcap, isneg;
421 case -1: barrel_endcap = 0; isneg = 0;
break;
422 case 1: barrel_endcap = 0; isneg = 1;
break;
424 ATH_MSG_WARNING(
"TRTDigitization::TRTNoise - identifier problems - skipping detector element!!");
436 digitVect.emplace_back(hitid,ndigit);
441 IdsFromChip.resize(0);
442 CrossTalkIdsOtherEnd.resize(0);
443 CrossTalkIds.resize(0);
454 const std::vector<float>& y_given_x,
456 const float& max_x ) {
459 unsigned int lower_index;
460 double fraction_into_bin;
466 return y_given_x.front();
470 bin_withfrac = (
x-min_x)*(y_given_x.size()-1)/(max_x-min_x);
471 lower_index =
static_cast<unsigned int>(bin_withfrac);
474 if ( lower_index >= y_given_x.size()-1 ) {
475 return y_given_x.back();
479 fraction_into_bin = bin_withfrac - lower_index;
480 return (1.-fraction_into_bin) * y_given_x[lower_index] + fraction_into_bin * y_given_x[lower_index+1];
488 std::vector<float>& x_given_y,
499 if ( y_given_x.front() < y_given_x.back() ) {
502 min_y = y_given_x.front();
503 max_y = y_given_x.back();
506 min_y = y_given_x.back();
507 max_y = y_given_x.front();
510 const unsigned int n(y_given_x.size());
511 if ( x_given_y.size() !=
n ) {
516 const float step_y((max_y-min_y)/(
n-1));
517 const float step_x((max_x-min_x)/(
n-1));
519 unsigned int searchindex = rising ? 0 :
n-1;
521 x_given_y.front() = rising ? min_x : max_x;
522 for (
unsigned int i = 1;
i <
n-1; ++
i) {
523 yval = min_y +
i*step_y;
527 while ( y_given_x[searchindex] <
yval ) { ++searchindex; };
528 x_given_y[
i] = min_x + searchindex*step_x;
530 while ( y_given_x[searchindex]<
yval ) { --searchindex; };
531 x_given_y[
i] = min_x + searchindex*step_x;
534 x_given_y.back() = rising ? max_x : min_x;
540 const float & min_lt2na,
541 const float & max_lt2na,
542 const float relativeLTFluct,
543 float & new_min_lt2na,
544 float & new_max_lt2na,
545 const unsigned int& number_new_bins )
550 std::vector<float> new_nl_given_lt2na(number_new_bins);
551 constexpr
double reciprocalSqrt2Pi = M_2_SQRTPI * 0.5 * M_SQRT1_2;
552 new_min_lt2na = min_lt2na;
553 new_max_lt2na = relativeLTFluct < 0.4 ? max_lt2na/(1.0-2.0*relativeLTFluct) : 5*max_lt2na;
555 for (
unsigned int i = 0;
i<number_new_bins;++
i) {
556 const float new_lt2naval(new_min_lt2na + (new_max_lt2na-new_min_lt2na)*
static_cast<float>(
i)/(number_new_bins-1));
557 float sigma = new_lt2naval*relativeLTFluct;
560 else {
sigma = 1.0e-8; }
562 const float lowerintrange(new_lt2naval - 5.0*
sigma);
563 float upperintrange(new_lt2naval + 5.0*
sigma);
564 if (upperintrange>max_lt2na) {
565 upperintrange = max_lt2na;
567 const double du((upperintrange-lowerintrange)/100.0);
569 const double minusoneover2sigmasq(- 1.0 / (2.0*
sigma*
sigma));
571 for (
double u(lowerintrange);
u < upperintrange;
u += du) {
573 exp(minusoneover2sigmasq * (
u-new_lt2naval) * (
u-new_lt2naval));
576 new_nl_given_lt2na[
i] =
sum;
579 nl_given_lt2na.resize(number_new_bins);
580 copy(new_nl_given_lt2na.begin(),
581 new_nl_given_lt2na.end(),
582 nl_given_lt2na.begin());
590 const int mask(0x0000001F);
591 const int word_shift(5);
592 int trtID, ringID, moduleID, layerID, strawID;
593 int wheelID, planeID, sectorID;
598 if ( !(hitID & 0x00200000) ) {
599 strawID = hitID &
mask;
600 hitID >>= word_shift;
601 layerID = hitID &
mask;
602 hitID >>= word_shift;
603 moduleID = hitID &
mask;
604 hitID >>= word_shift;
605 ringID = hitID &
mask;
606 trtID = hitID >> word_shift;
609 if ( barrelElement ) {
610 IdLayer = barrelElement->
identify();
613 ATH_MSG_ERROR(
"Could not find detector element for barrel identifier with "
614 <<
"(ipos,iring,imod,ilayer,istraw) = ("
615 << trtID <<
", " << ringID <<
", " << moduleID <<
", "
616 << layerID <<
", " << strawID <<
")");
619 strawID = hitID &
mask;
620 hitID >>= word_shift;
621 planeID = hitID &
mask;
622 hitID >>= word_shift;
623 sectorID = hitID &
mask;
624 hitID >>= word_shift;
625 wheelID = hitID &
mask;
626 trtID = hitID >> word_shift;
629 if (trtID == 3) { trtID = 0; }
634 if ( endcapElement ) {
635 IdLayer = endcapElement->
identify();
638 ATH_MSG_ERROR(
"Could not find detector element for endcap identifier with "
639 <<
"(ipos,iwheel,isector,iplane,istraw) = ("
640 << trtID <<
", " << wheelID <<
", " << sectorID <<
", "
641 << planeID <<
", " << strawID <<
")");
642 ATH_MSG_ERROR(
"If this happens very rarely, don't be alarmed "
643 "(it is a Geant4 'feature')");
644 ATH_MSG_ERROR(
"If it happens a lot, you probably have misconfigured geometry "