73 if(energyDeposit==0.)
return {};
81 idHelper.
gasGap(offlineId),
92 if( !detEl ){
return {}; }
98 constexpr double length_tolerance = 0.01;
114 Amg::Vector2D posOnSurf_wire{0.5 * (hitOnSurface_wire + pre_pos_wire_surf).block<2,1>(0,0)};
131 if ((wire_number < 1) || (wire_number > number_wires)) {
135 if ((wire_number < 1) || (wire_number > number_wires)) {
142 double dist_wire = ionization.
distance;
143 if (dist_wire > 0.) {
153 double dist_wire_adj = ion_adj.
distance;
154 if ((dist_wire_adj > 0.) && (dist_wire_adj < dist_wire)) {
155 dist_wire = dist_wire_adj;
156 wire_number += adjacent;
157 ionization = std::move(ion_adj);
160 ATH_MSG_DEBUG(
"Failed to get the distance between the wire number = " << wire_number
162 <<
". Number of wires = " << number_wires
168 posOnSurf_wire = ionization.
posOnWire.block<2,1>(0,0);
186 const double wire_pitch = detEl->
wirePitch();
187 if ((dist_wire > 0.) && (std::abs(hit.
particleEncoding()) == 13) && (dist_wire > (wire_pitch/2))) {
188 ATH_MSG_DEBUG(
"Distance to the nearest wire (" << dist_wire <<
") is greater than expected.");
198 if (dist_wire > wire_pitch) {
208 double gamma_mpv = (par_kappa - 1) * par_theta;
210 if (gamma_mpv < 0.) {gamma_mpv = 0.;}
211 const double t0_par = most_prob_time - gamma_mpv;
218 double digit_time = t0_par + CLHEP::RandGamma::shoot(condContainers.
rndmEngine, par_kappa, 1/par_theta);
224 constexpr int shoot_limit = 4;
225 int shoot_counter = 0;
226 while (digit_time < 0.) {
227 if (shoot_counter > shoot_limit) {
231 digit_time = t0_par + CLHEP::RandGamma::shoot(condContainers.
rndmEngine, par_kappa, 1/par_theta);
236 <<
", time = " << digit_time
237 <<
", k parameter = " << par_kappa
238 <<
", theta parameter = " << par_theta
239 <<
", most probable time = " << most_prob_time);
253 const double stripPropagationTime = 0.;
255 double sDigitTimeWire = digit_time;
256 double sDigitTimePad = sDigitTimeWire;
257 double sDigitTimeStrip = sDigitTimeWire + stripPropagationTime;
280 detEl->
spacePointPosition(newId, hitOnSurface_strip.x(), hitOnSurface_strip.y(), posAfterAsBuilt);
281 posOnSurf_strip = posAfterAsBuilt.block<2,1>(0,0);
283 posOnSurf_strip = hitOnSurface_strip.block<2,1>(0,0);
286 bool insideBounds = SURF_STRIP.
insideBounds(posOnSurf_strip);
288 ATH_MSG_DEBUG(
"Outside of the strip surface boundary : " <<
m_idHelperSvc->toString(newId) <<
"; local position " <<posOnSurf_strip );
294 int stripNumber = detEl->
stripNumber(posOnSurf_strip, newId);
295 if( stripNumber == -1 ){
297 const double new_posX = (posOnSurf_strip.x() > 0.0)? posOnSurf_strip.x() - length_tolerance
298 : posOnSurf_strip.x() + length_tolerance;
299 const Amg::Vector2D new_position(new_posX, posOnSurf_strip.y());
300 stripNumber = detEl->
stripNumber(new_position, newId);
302 if (stripNumber < 1) {
304 ATH_MSG_WARNING(
"Position on strip surface = (" << posOnSurf_strip.x() <<
", " << posOnSurf_strip.y() <<
")");
310 if(!
isValid && stripNumber != -1) {
316 const double stripHalfPitch = detEl->
channelPitch(newId)*0.5;
324 const double ionized_charge = (5.65E-6)*energyDeposit/CLHEP::keV;
337 const double total_charge = gain*ionized_charge;
341 const double tan_theta = GLODIRE.perp()/GLODIRE.z();
345 const double cluster_posX = posOnSurf_strip.x();
346 double peak_position = CLHEP::RandGaussZiggurat::shoot(condContainers.
rndmEngine, cluster_posX,
m_StripResolution*angle_dependency);
350 const double norm = 0.5 * total_charge;
354std::unique_ptr<TF1> clusterProfile = std::make_unique<TF1>(
"fgaus",
355 "0.5 * [2] / (sqrt(2 * TMath::Pi()) * [0]) * exp(-0.5 * (x / [0])^2) + "
356 "0.5 * [2] / (sqrt(2 * TMath::Pi()) * [1]) * exp(-0.5 * (x / [1])^2)", -300., 300.);
362 constexpr double tolerance_charge = 0.0005;
364 constexpr unsigned int max_neighbor = 10;
367 for (
unsigned int iStrip = 0; iStrip <= max_neighbor; ++iStrip) {
368 int currentStrip = stripNumber + iStrip;
369 if (currentStrip > NumberOfStrips)
break;
373 channelType, currentStrip,
isValid);
382 double x_relative = locpos.x() - peak_position;
384 double charge = std::hypot(1,
m_chargeAngularFactor * tan_theta) * clusterProfile->Integral(x_relative/(2*stripHalfPitch) - 0.5, x_relative/(2*stripHalfPitch) + 0.5);
386 if (
charge < tolerance_charge)
break;
389 double strip_time = sDigitTimeStrip;
394 int indexFromMiddleStrip = iStrip;
395 if ((iStrip > 0) && ((x_relative + (0.75 - iStrip * 2) * stripHalfPitch) < 0))
396 indexFromMiddleStrip = iStrip - 1;
404 <<
", time = " << strip_time <<
", time offset = " << strip_time-sDigitTimeStrip
405 <<
", neighbor index = " << iStrip
411 for (
unsigned int iStrip = 1; iStrip <= max_neighbor; ++iStrip) {
412 int currentStrip = stripNumber - iStrip;
413 if (currentStrip < 1)
break;
424 double x_relative = locpos.x() - peak_position;
425 double charge = std::hypot(1,
m_chargeAngularFactor * tan_theta) * clusterProfile->Integral(x_relative/(2*stripHalfPitch) - 0.5, x_relative/(2*stripHalfPitch) + 0.5);
426 if (
charge < tolerance_charge)
break;
429 double strip_time = sDigitTimeStrip;
432 int indexFromMiddleStrip = ((x_relative + (iStrip * 2 - 0.75) * stripHalfPitch) > 0)? iStrip - 1 : iStrip;
439 <<
", time = " << strip_time <<
", time offset = " << strip_time-sDigitTimeStrip
440 <<
", neighbor index = " << iStrip
458 idHelper.
gasGap(layid), channelType, 1);
464 const Amg::Vector2D posOnSurf_pad(hitOnSurface_pad.x(), hitOnSurface_pad.y());
470 int padNumber = detEl->
stripNumber(posOnSurf_pad, PAD_ID);
471 if( padNumber == -1 ){
473 const double new_posX = (posOnSurf_pad.x()>0.0)? posOnSurf_pad.x()-length_tolerance
474 : posOnSurf_pad.x()+length_tolerance;
475 const double new_posY = (posOnSurf_pad.y()>0.0)? posOnSurf_pad.y()-length_tolerance
476 : posOnSurf_pad.y()+length_tolerance;
478 padNumber = detEl->
stripNumber(new_position, PAD_ID);
482 ATH_MSG_WARNING(
"Position on pad surface = (" << posOnSurf_pad.x() <<
", " << posOnSurf_pad.y() <<
")");
505 double deltaX = halfPadWidthX - std::abs(
diff.x());
506 double deltaY= halfPadWidthY - std::abs(
diff.y());
511 if (deltaX < 0.) deltaX = 0.1;
512 if (deltaY < 0.) deltaY = 0.1;
518 int newPhi =
diff.x() > 0 ? padEtaPhi.second-1 : padEtaPhi.second+1;
519 int newEta =
diff.y() > 0 ? padEtaPhi.first+1 : padEtaPhi.first-1;
523 if (isNeighX && isNeighY && validEta && validPhi){
526 channelType, padEtaPhi.first, newPhi,
isValid);
528 channelType, newEta, padEtaPhi.second,
isValid);
530 channelType, newEta, newPhi,
isValid);
535 addDigit(digits, neigh_ID_X, bctag, sDigitTimePad, xQfraction*(1.-yQfraction)*0.5*total_charge);
536 addDigit(digits, neigh_ID_Y, bctag, sDigitTimePad, yQfraction*(1.-xQfraction)*0.5*total_charge);
537 addDigit(digits, neigh_ID_XY, bctag, sDigitTimePad, xQfraction*yQfraction*0.5*total_charge);
538 addDigit(digits, newId, bctag, sDigitTimePad, (1.-xQfraction-yQfraction+xQfraction*yQfraction)*0.5*total_charge);
539 }
else if (isNeighX && validPhi){
542 channelType, padEtaPhi.first, newPhi,
isValid);
547 addDigit(digits, newId, bctag, sDigitTimePad, (1.-xQfraction)*0.5*total_charge);
548 addDigit(digits, neigh_ID, bctag, sDigitTimePad, xQfraction*0.5*total_charge);
550 else if (isNeighY && validEta){
553 channelType, newEta, padEtaPhi.second,
isValid);
558 addDigit(digits, newId, bctag, sDigitTimePad, (1.-yQfraction)*0.5*total_charge);
559 addDigit(digits, neigh_ID, bctag, sDigitTimePad, yQfraction*0.5*total_charge);
565 addDigit(digits, newId, bctag, sDigitTimePad, 0.5*total_charge);
569 else if(padNumber != -1) {
574 ATH_MSG_DEBUG(
"Outside of the pad surface boundary :" <<
m_idHelperSvc->toString(PAD_ID)<<
" local position " <<posOnSurf_pad );
591 idHelper.
gasGap(layid), channelType, 1);
599 int wiregroupNumber = detEl->
stripNumber(posOnSurf_wire, WIREGP_ID);
600 if( wiregroupNumber == -1 ){
602 const double new_posX = (posOnSurf_wire.x() > 0.0)? posOnSurf_wire.x() - length_tolerance
603 : posOnSurf_wire.x() + length_tolerance;
604 const Amg::Vector2D new_position(new_posX, posOnSurf_wire.y());
605 wiregroupNumber = detEl->
stripNumber(new_position, WIREGP_ID);
607 if (wiregroupNumber < 1) {
609 ATH_MSG_WARNING(
"Position on wire surface = (" << posOnSurf_wire.x() <<
", " << posOnSurf_wire.y() <<
")");
616 channelType, wiregroupNumber,
isValid);
620 if(wiregroupNumber>=1&&wiregroupNumber<=NumberOfWiregroups) {
621 addDigit(digits, newId, bctag, sDigitTimeWire, total_charge);
624 else if (wiregroupNumber != -1){
629 ATH_MSG_DEBUG(
"Outside of the wire surface boundary :" <<
m_idHelperSvc->toString(WIREGP_ID)<<
" local position " <<posOnSurf_wire );