13 #include "CLHEP/Random/RandFlat.h" 
   14 #include "CLHEP/Random/RandomEngine.h" 
   15 #include "CLHEP/Units/SystemOfUnits.h" 
   16 #include "GaudiKernel/MsgStream.h" 
   26 #include "GaudiKernel/Bootstrap.h" 
   39     : 
AthMessaging(
"TgcDigitMaker"), m_doFourBunchDigitization(doFourBunch) {
 
   82     return StatusCode::SUCCESS;
 
   89     const TGCSimHit* hit, 
const double globalHitTime,
 
   92     CLHEP::HepRandomEngine* rndmEngine) {
 
   94     constexpr 
float sensor_propagation_time =
 
  102     constexpr 
float wire_pitch = 1.8 * 
CLHEP::mm;
 
  103     constexpr 
float zwidth_frame = 17. * 
CLHEP::mm;
 
  108     int Id = hit->
TGCid();
 
  135                         << 
"context begin_index = " << tgcContext.
begin_index()
 
  136                         << 
" context end_index  = " << tgcContext.
end_index()
 
  137                         << 
" the identifier is " << elemId);
 
  141     std::unique_ptr<TgcDigitCollection> digits =
 
  142         std::make_unique<TgcDigitCollection>(elemId, coll_hash);
 
  145     float height = tgcChamber->
getRsize();
 
  146     float hmin = sqrt(
pow(centreChamber.x(), 2) + 
pow(centreChamber.y(), 2)) -
 
  156     float distanceZ = 1.4 * 
CLHEP::mm / direCos[0] * direCos[2];
 
  157     float zLocal = localPos.z() + distanceZ;
 
  160     float distanceY = 1.4 * 
CLHEP::mm / direCos[0] * direCos[1];
 
  164     float yLocal = ySign * (localPos.y() + distanceY);
 
  169     double tofCorrection =
 
  170         (sqrt(
pow(hmin + zwidth_frame, 2) + 
pow(centreChamber.z(), 2)) /
 
  174     float bunchTime = globalHitTime - tofCorrection;
 
  176     static const float jitterInitial = 9999.;
 
  177     float jitter = jitterInitial;  
 
  198              kWIRE, rndmEngine))) {  
 
  201         float posInWireGroup[2] = {0., 0.};
 
  202         for (
int iPosition = 0; iPosition < 2; iPosition++) {
 
  203             int nWireOffset = (std::abs(
stationEta) == 5 ||
 
  211             double zPosInSensArea =
 
  212                 zLocal + 
static_cast<double>(tgcChamber->
nWires(ilyr) -
 
  217             if (zPosInSensArea < 0. ||
 
  218                 zPosInSensArea > tgcChamber->
nWires(ilyr) * wire_pitch) {
 
  219                 iWireGroup[iPosition] = 0;
 
  220                 posInWireGroup[iPosition] = 0.;
 
  222                     "executeDigi(): Wire: Hit position located at outside of a " 
  226                     << 
" position: " << zPosInSensArea << 
" xlocal: " << zLocal
 
  227                     << 
" dir cosine: " << direCos[0] << 
"/" << direCos[1] << 
"/" 
  229                     << 
" active region: " << height - zwidth_frame * 2.);
 
  233                 while (wire_pitch * (
static_cast<float>(wire_index)) <
 
  235                        igang <= tgcChamber->nWireGangs(ilyr)) {
 
  236                     wire_index += tgcChamber->
nWires(ilyr, igang);
 
  239                 posInWireGroup[iPosition] =
 
  240                     (zPosInSensArea / wire_pitch -
 
  241                      (
static_cast<float>(wire_index))) /
 
  243                             tgcChamber->
nWires(ilyr, igang - 1))) +
 
  246                 iWireGroup[iPosition] = ((1 == igang) ? 1 : igang - 1);
 
  250         unsigned int jWG[2] = {
 
  251             (iWireGroup[0] <= iWireGroup[1]) ? (
unsigned int)(0)
 
  253             (iWireGroup[0] <= iWireGroup[1]) ? (
unsigned int)(1)
 
  254                                              : (
unsigned int)(0)};
 
  255         int iWG[2] = {iWireGroup[jWG[0]], iWireGroup[jWG[1]]};
 
  256         float posInWG[2] = {posInWireGroup[jWG[0]], posInWireGroup[jWG[1]]};
 
  257         if (iWG[0] != iWG[1]) {
 
  258             ATH_MSG_DEBUG(
"executeDigi(): Multihits found in WIRE GROUPs:" 
  259                           << iWG[0] << 
" " << iWG[1]);
 
  263         for (
int iwg = iWG[0]; iwg <= iWG[1]; iwg++) {
 
  264             if (1 <= iwg && iwg <= tgcChamber->nWireGangs(ilyr)) {
 
  266                 float wire_timeOffset =
 
  272                 if (iStationName > 46)
 
  280                 float ySignPhi = (
stationPhi % 2 == 1) ? -1. : +1.;
 
  284                 float wTimeDiffByRadiusOfInner =
 
  288                     bunchTime + jitter + wTimeDiffByRadiusOfInner;
 
  289                 float wASDDis{-1000.};
 
  290                 if (ASDpos != 
nullptr) {
 
  295                         wASDDis + (ySignPhi * yLocal +
 
  298                         sensor_propagation_time *
 
  301                         cable_propagation_time * wASDDis;
 
  314                         "WireGroup: digitized time " 
  315                         << digit_time << 
" ns is outside of time window from " 
  316                         << wire_timeOffset << 
". bunchTime: " << bunchTime
 
  317                         << 
" time jitter: " << jitter << 
" propagation time: " 
  318                         << sensor_propagation_time *
 
  321                                cable_propagation_time * wASDDis
 
  322                         << 
" time difference by cable radius of inner station: " 
  323                         << wTimeDiffByRadiusOfInner);
 
  328                     addDigit(newId, bctag, digits.get());
 
  332                                         posInWG[0], digit_time, wire_timeOffset,
 
  333                                         rndmEngine, digits.get());
 
  337                         "WireGroup: newid breakdown digitTime x/y/z direcos " 
  338                         "height_gang bctag: " 
  341                         << 
"WIRE/" << iwg << 
" " << digit_time << 
" " 
  342                         << localPos.x() << 
"/" << localPos.y() << 
"/" 
  343                         << localPos.z() << 
" " << direCos.x() << 
"/" 
  344                         << direCos.y() << 
"/" << direCos.z() << 
" " << height
 
  345                         << 
" " << tgcChamber->
nWires(ilyr, iwg) << 
" " 
  350                     "Wire Gang id is out of range. id, x/y/z, height: " 
  351                     << iwg << 
" " << localPos.x() << 
"/" << localPos.y() << 
"/" 
  352                     << localPos.z() << 
" " << height);
 
  360     if ((ilyr != 2 || (
stationName.compare(0, 2, 
"T1") !=
 
  364               sensor, rndmEngine)) ||  
 
  373         float posInStrip[2] = {0., 0.};
 
  375         for (
int iPosition = 0; iPosition < 2; iPosition++) {
 
  378             float zPos = zLocal + height / 2. - zwidth_frame;
 
  380                 iStrip[iPosition] = 0;
 
  381                 posInStrip[iPosition] = 0.;
 
  383                     "Strip: Hit position located at outside of a sensitive " 
  384                     "volume, id, position, xlocal0/1, dir cosine: " 
  386                     << 
"/" << ilyr << zPos << 
" " << zLocal << 
" " << direCos[0]
 
  387                     << 
"/" << direCos[1] << 
"/" << direCos[2]);
 
  388             } 
else if (zPos > height - zwidth_frame * 2.) {
 
  389                 iStrip[iPosition] = tgcChamber->
nStrips(ilyr) + 1;
 
  390                 posInStrip[iPosition] = 0.;
 
  392                     "Strip: Hit position located at outside of a sensitive " 
  393                     "volume, id, position, active region: " 
  395                     << 
"/" << ilyr << zPos << 
" " 
  396                     << height - zwidth_frame * 2.);
 
  405                 float phiLocal = atan2(yLocal, zLocal + height / 2. + hmin);
 
  408                     "dphi, phiLocal, yLocal, zLocall+ height/2.+hmin: " 
  409                     << dphi << 
" " << phiLocal << 
" " << yLocal << 
" " 
  410                     << zLocal + height / 2. + hmin);
 
  415                     istr = 
static_cast<int>(floor(phiLocal / dphi + 15.75)) + 1;
 
  416                     posInStrip[iPosition] =
 
  417                         phiLocal / dphi + 15.75 - 
static_cast<float>(istr - 1);
 
  419                         istr = 
static_cast<int>(floor(
 
  420                                    (phiLocal - dphi * 14.25) / (dphi / 2.))) +
 
  422                         posInStrip[iPosition] =
 
  423                             (phiLocal - dphi * 14.25) / (dphi / 2.) -
 
  424                             static_cast<float>(istr - 31);
 
  427                     istr = 
static_cast<int>(floor(phiLocal / dphi + 16.25)) + 1;
 
  428                     posInStrip[iPosition] =
 
  429                         phiLocal / dphi + 16.25 - 
static_cast<float>(istr - 1);
 
  431                         istr = 
static_cast<int>(floor(
 
  432                                    (phiLocal + dphi * 14.25) / (dphi / 2.))) +
 
  434                         posInStrip[iPosition] =
 
  435                             (phiLocal + dphi * 14.25) / (dphi / 2.) -
 
  436                             static_cast<float>(istr - 3);
 
  441                     posInStrip[iPosition] = 0.;
 
  442                 } 
else if (32 < istr) {
 
  444                     posInStrip[iPosition] = 0.;
 
  446                 iStrip[iPosition] = istr;
 
  450         unsigned int jStr[2] = {
 
  451             (iStrip[0] <= iStrip[1]) ? (
unsigned int)(0) : (
unsigned int)(1),
 
  452             (iStrip[0] <= iStrip[1]) ? (
unsigned int)(1) : (
unsigned int)(0)};
 
  453         int iStr[2] = {iStrip[jStr[0]], iStrip[jStr[1]]};
 
  454         float posInStr[2] = {posInStrip[jStr[0]], posInStrip[jStr[1]]};
 
  455         if (iStr[0] != iStr[1]) {
 
  461         float strip_timeOffset =
 
  466         for (
int istr = iStr[0]; istr <= iStr[1]; istr++) {
 
  467             if (1 <= istr && istr <= 32) {
 
  469                 if (jitter > jitterInitial - 0.1) {
 
  478                 float sTimeDiffByRadiusOfInner =
 
  483                     sensor_propagation_time *
 
  484                         (height / 2. + zwidth_frame + zSignEta * zLocal) +
 
  485                     sTimeDiffByRadiusOfInner;
 
  486                 float sASDDis{-1000};
 
  487                 if (ASDpos != 
nullptr) {
 
  492                     float sCableDis = sASDDis + (height / 2. + zwidth_frame +
 
  495                                   sASDDis * cable_propagation_time;
 
  506                         "Strip: Digitized time is outside of time window. " 
  507                         << sDigitTime << 
" bunchTime: " << bunchTime
 
  508                         << 
" time jitter: " << jitter << 
" propagation time: " 
  509                         << sensor_propagation_time *
 
  510                                (height / 2. + zwidth_frame + zSignEta * zLocal)
 
  511                         << 
" time difference by cable radius of inner station: " 
  512                         << sTimeDiffByRadiusOfInner);
 
  517                     addDigit(newId, bctag, digits.get());
 
  519                     if (istr == iStr[0]) {
 
  521                                         iStr[0], posInStr[0], sDigitTime,
 
  522                                         strip_timeOffset, rndmEngine,
 
  527                         "Strip: newid breakdown digitTime x/y/z direcos " 
  530                         << 
"/" << 
stationPhi << 
"/" << ilyr << 
"/" << sensor
 
  531                         << 
"/" << istr << 
" " << sDigitTime << 
" " 
  532                         << localPos.x() << 
"/" << localPos.y() << 
"/" 
  533                         << localPos.z() << 
" " << direCos.x() << 
"/" 
  534                         << direCos.y() << 
"/" << direCos.z() << 
" " 
  535                         << height / 2. + hmin << 
" " << bctag);
 
  539                               << ilyr << 
" " << istr);
 
  544     return digits.release();
 
  549     const char* 
const fileName = 
"TGC_Digitization_timejitter.dat";
 
  553     if (!fileWithPath.empty()) {
 
  554         ifs.open(fileWithPath.c_str(), std::ios::in);
 
  558         return StatusCode::FAILURE;
 
  564         return StatusCode::FAILURE;
 
  578             "readFileOfTimeJitter(): Timejitter, angle, Number of bins, prob. " 
  582         for (
int j = 0; j < 41 ; j++) {
 
  595     return StatusCode::SUCCESS;
 
  599                                 CLHEP::HepRandomEngine* rndmEngine)
 const {
 
  600     float injectionAngle =
 
  601         atan2(fabs(direCosLocal[2]), fabs(direCosLocal[0])) / 
CLHEP::degree;
 
  603     int ithAngle = 
static_cast<int>(injectionAngle / 5.);
 
  604     float wAngle = injectionAngle / 5. - 
static_cast<float>(ithAngle);
 
  610         jthAngle = ithAngle + 1;
 
  617     while (
prob > probRef) {
 
  618         prob = CLHEP::RandFlat::shoot(rndmEngine, 0.0, 1.0);
 
  619         jitter = CLHEP::RandFlat::shoot(rndmEngine, 0.0, 1.0) * 40. *
 
  621         int ithJitter = 
static_cast<int>(jitter);
 
  631                                     CLHEP::HepRandomEngine* rndmEngine)
 const {
 
  632     if (CLHEP::RandFlat::shoot(rndmEngine, 0.0, 1.0) < 
m_efficiency[sensor])
 
  635                   << sensor << 
"(0=WIRE,1=STRIP)");
 
  650                                   const double offset)
 const {
 
  651     const double calc_coll_time =
 
  658     if (0. < calc_coll_time && calc_coll_time < window) {
 
  676         if ((bctag >> (bc - 1)) & 0
x1) {
 
  677             bool duplicate = 
false;
 
  678             for (
const auto digit : *digits) {
 
  679                 if (
id == 
digit->identify() && 
digit->bcTag() == bc) {
 
  685                 std::unique_ptr<TgcDigit> multihitDigit =
 
  686                     std::make_unique<TgcDigit>(
id, bc);
 
  687                 digits->push_back(multihitDigit.release());
 
  697     for (iStationName = 0; iStationName < 
N_STATIONNAME; iStationName++) {
 
  711     const std::string 
fileName = 
"TGC_Digitization_energyThreshold.dat";
 
  713     if (fileWithPath.empty()) {
 
  714         ATH_MSG_FATAL(
"readFileOfEnergyThreshold(): Could not find file " 
  716         return StatusCode::FAILURE;
 
  721     ifs.open(fileWithPath.c_str(), std::ios::in);
 
  723         ATH_MSG_FATAL(
"readFileOfEnergyThreshold(): Could not open file " 
  725         return StatusCode::FAILURE;
 
  728     double energyThreshold;
 
  734                       << 
" stationName= " << iStationName << 
" stationEta= " 
  737                       << 
" energyThreshold(MeV)= " << energyThreshold);
 
  753         if (gasGap < 0 || gasGap >= 
N_GASGAP)
 
  769     return StatusCode::SUCCESS;
 
  777     SmartIF<IGeoModelSvc> geoModel{Gaudi::svcLocator()->service(
"GeoModelSvc")};
 
  782     std::string atlasVersion = geoModel->atlasVersion();
 
  784     SmartIF<IRDBAccessSvc> rdbAccess{Gaudi::svcLocator()->service(
"RDBAccessSvc")};
 
  791         rdbAccess->getRecordsetPtr(
"AtlasCommon", atlasVersion, 
"ATLAS");
 
  793     if (atlasCommonRec->size() == 0)
 
  796         std::string configVal = (*atlasCommonRec)[0]->getString(
"CONFIG");
 
  797         if (configVal == 
"RUN1")
 
  799         else if (configVal == 
"RUN2")
 
  801         else if (configVal == 
"RUN3")
 
  804         else if (configVal == 
"RUN4")
 
  810                         "Unexpected value for geometry config read from the database: " 
  822     for (iStationName = 0; iStationName < 
N_STATIONNAME; iStationName++) {
 
  836       return StatusCode::FAILURE;
 
  842         fileName = 
"TGC_Digitization_deadChamber.dat";
 
  844         fileName = 
"TGC_Digitization_2016deadChamber.dat";
 
  846         fileName = 
"TGC_Digitization_NOdeadChamber.dat";
 
  849                                     << 
" is unexpected in TgcDigitMaker - " 
  850                                        "using NOdeadChamber configuration.");
 
  851         return StatusCode::FAILURE;
 
  854     if (fileWithPath.empty()) {
 
  855         ATH_MSG_FATAL(
"readFileOfDeadChamber(): Could not find file " 
  857         return StatusCode::FAILURE;
 
  862     ifs.open(fileWithPath.c_str(), std::ios::in);
 
  864         ATH_MSG_FATAL(
"readFileOfDeadChamber(): Could not open file " 
  866         return StatusCode::FAILURE;
 
  870     unsigned int nDeadChambers = 0;
 
  879                       << 
" stationName= " << iStationName << 
" stationEta= " 
  896         if (gasGap < 0 || gasGap >= 
N_GASGAP)
 
  910     ATH_MSG_INFO(
"readFileOfDeadChamber: the number of dead chambers = " 
  913     return StatusCode::SUCCESS;
 
  920     for (iStationName = 0; iStationName < 
N_STATIONNAME; iStationName++) {
 
  929     const std::string 
fileName = 
"TGC_Digitization_StripPosition.dat";
 
  931     if (fileWithPath.empty()) {
 
  932         ATH_MSG_FATAL(
"readFileOfStripPosition(): Could not find file " 
  934         return StatusCode::FAILURE;
 
  939     ifs.open(fileWithPath.c_str(), std::ios::in);
 
  941         ATH_MSG_FATAL(
"readFileOfStripPosition(): Could not open file " 
  943         return StatusCode::FAILURE;
 
  951                       << 
" stationName= " << iStationName << 
" stationEta= " 
  953                       << 
" StripPosition= " << strippos);
 
  975     return StatusCode::SUCCESS;
 
  991     double energyThreshold = +999999.;
 
 1008                     << sensor << 
" energyThreshold(MeV)= " << energyThreshold);
 
 1010     return energyThreshold;
 
 1017     const float posInChan, 
const float digitTime, 
const float time_offset,
 
 1032     float prob1CrossTalk =
 
 1034     float prob11CrossTalk =
 
 1036     float prob20CrossTalk =
 
 1038     float prob21CrossTalk =
 
 1041     int nCrossTalks_neg = 0;
 
 1042     int nCrossTalks_pos = 0;
 
 1044     if (posInChan < prob1CrossTalk) {
 
 1045         nCrossTalks_neg = 1;  
 
 1046     } 
else if (posInChan > 1. - prob1CrossTalk) {
 
 1047         nCrossTalks_pos = 1;  
 
 1049         double prob = CLHEP::RandFlat::shoot(rndmEngine, 0.0, 1.0);
 
 1050         if (
prob < prob11CrossTalk / (1. - 2. * prob1CrossTalk)) {
 
 1051             nCrossTalks_neg = 1;
 
 1052             nCrossTalks_pos = 1;  
 
 1053         } 
else if (
prob < (prob20CrossTalk + prob11CrossTalk) /
 
 1054                               (1. - 2. * prob1CrossTalk)) {
 
 1055             if (posInChan < 0.5) {
 
 1056                 nCrossTalks_neg = 2;
 
 1059                 nCrossTalks_pos = 2;
 
 1063                 (prob20CrossTalk + prob11CrossTalk + 2. * prob21CrossTalk) /
 
 1064                     (1. - 2. * prob1CrossTalk)) {
 
 1065                 if (posInChan < 0.5) {
 
 1066                     nCrossTalks_neg = 2;
 
 1067                     nCrossTalks_pos = 1;
 
 1070                     nCrossTalks_neg = 1;
 
 1071                     nCrossTalks_pos = 2;
 
 1077     if (nCrossTalks_neg == 0 && nCrossTalks_pos == 0)
 
 1081     float dt = digitTime;
 
 1090     for (
int jChan = 
channel - nCrossTalks_neg;
 
 1091          jChan <= 
channel + nCrossTalks_pos; jChan++) {
 
 1092         if (jChan == 
channel || jChan < 1 || jChan > maxChannelNumber)
 
 1103     bool v_isDeadChamber = 
true;
 
 1129                     << 
" isDeadChamber= " << v_isDeadChamber);
 
 1131     return v_isDeadChamber;
 
 1135     int iStationName = 0;
 
 1153     return iStationName;
 
 1181     if (iStationName != 47 && iStationName != 48)
 
 1200     const int channel, 
const float position)
 const {
 
 1203     int phiId = (iStationName >= 47) ? 
stationPhi : 0x1f;
 
 1206     unsigned int asdNo = 
static_cast<unsigned int>(
channel - 1) /
 
 1209     float asd_position = 0.;
 
 1211     auto it = map.find(chamberId);
 
 1213     if (
it != map.end()) {
 
 1218                         << 
", phi=" << phiId);
 
 1221     float distance = fabs(position - asd_position);
 
 1230         (station_num << 3) + static_cast<uint16_t>(std::abs(
station_eta));
 
 1231     return ((sensor == TgcSensor::kSTRIP)
 
 1233                 : readCdo->
wireOffset.find(chamberId)->second);
 
 1238     const TgcSensor sensor, 
const unsigned int index_prob) {
 
 1239     if (readCdo == 
nullptr)
 
 1241     return ((sensor == TgcSensor::kSTRIP)