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 "