ATLAS Offline Software
Classes | Public Types | Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | Static Private Attributes | List of all members
sTgcDigitMaker Class Reference

#include <sTgcDigitMaker.h>

Inheritance diagram for sTgcDigitMaker:
Collaboration diagram for sTgcDigitMaker:

Classes

struct  DigiConditions
 Digitize a given hit, determining the time and charge spread on wires, pads and strips. More...
 
struct  GammaParameter
 Parameters of a gamma probability distribution function, required for estimating wire digit's time of arrival. More...
 
struct  Ionization
 Ionization object with distance, position on the hit segment and position on the wire. More...
 

Public Types

using sTgcDigitVec = std::vector< std::unique_ptr< sTgcDigit > >
 

Public Member Functions

 sTgcDigitMaker (const Muon::IMuonIdHelperSvc *idHelperSvc, const int channelTypes, double meanGasGain, bool doPadChargeSharing, double stripChargeScale)
 
virtual ~sTgcDigitMaker ()
 
StatusCode initialize ()
 Initializes sTgcHitIdHelper and sTgcIdHelper, and call the functions to read files containing digitization parameters. More...
 
sTgcDigitVec executeDigi (const DigiConditions &condContainers, const sTGCSimHit &hit) const
 
bool msgLvl (const MSG::Level lvl) const
 Test the output level. More...
 
MsgStream & msg () const
 The standard message stream. More...
 
MsgStream & msg (const MSG::Level lvl) const
 The standard message stream. More...
 
void setLevel (MSG::Level lvl)
 Change the current logging level. More...
 

Private Member Functions

StatusCode readFileOfTimeArrival ()
 Read share/sTGC_Digitization_timeArrival.dat. More...
 
StatusCode readFileOfTimeOffsetStrip ()
 Read share/sTGC_Digitization_timeOffsetStrip.dat. More...
 
Ionization pointClosestApproach (const MuonGM::sTgcReadoutElement *readoutEle, const Identifier &id, int wireNumber, const Amg::Vector3D &preStepPos, const Amg::Vector3D &postStepPos) const
 Determine the points where the distance between two segments is smallest. More...
 
double getTimeOffsetStrip (size_t neighbor_index) const
 Get digit time offset of a strip depending on its relative position to the strip at the centre of the cluster. More...
 
GammaParameter getGammaParameter (double distance) const
 Find the gamma pdf parameters of a given distance. More...
 
double getMostProbableArrivalTime (double distance) const
 Get the most probable time of arrival. More...
 
void initMessaging () const
 Initialize our message level and MessageSvc. More...
 

Static Private Member Functions

static void addDigit (sTgcDigitVec &digits, const Identifier &id, const uint16_t bctag, const double digittime, const double charge)
 
static double getPadChargeFraction (double distance)
 

Private Attributes

std::vector< GammaParameterm_gammaParameter
 
std::array< double, 5 > m_mostProbableArrivalTime {make_array<double, 5>(0.)}
 
std::array< double, 6 > m_timeOffsetStrip {make_array<double, 6>(0.)}
 
const Muon::IMuonIdHelperSvcm_idHelperSvc {nullptr}
 
int m_channelTypes {3}
 define offsets and widths of time windows for signals from wiregangs and strips. More...
 
double m_theta {0.8}
 
double m_meanGasGain {5.e4}
 
bool m_doPadSharing {false}
 
bool m_doTimeOffsetStrip {false}
 
double m_StripResolution {0.0949}
 
double m_posResIncident {1.}
 
double m_posResAngular {0.305/m_StripResolution}
 
double m_chargeAngularFactor {4.0}
 
double m_stripChargeScale {0.4}
 
std::string m_nm
 Message source name. More...
 
boost::thread_specific_ptr< MsgStream > m_msg_tls
 MsgStream instance (a std::cout like with print-out levels) More...
 
std::atomic< IMessageSvc * > m_imsg { nullptr }
 MessageSvc pointer. More...
 
std::atomic< MSG::Level > m_lvl { MSG::NIL }
 Current logging level. More...
 
std::atomic_flag m_initialized ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT
 Messaging initialized (initMessaging) More...
 

Static Private Attributes

static constexpr std::array< double, 4 > m_clusterProfile {0.350, 0.573, 0.186, 1.092}
 

Detailed Description

for SCT_ChargeTrappingTool

All functionality of sTGC digitization is implemented to this class.

Definition at line 36 of file sTgcDigitMaker.h.

Member Typedef Documentation

◆ sTgcDigitVec

using sTgcDigitMaker::sTgcDigitVec = std::vector<std::unique_ptr<sTgcDigit> >

Definition at line 64 of file sTgcDigitMaker.h.

Constructor & Destructor Documentation

◆ sTgcDigitMaker()

sTgcDigitMaker::sTgcDigitMaker ( const Muon::IMuonIdHelperSvc idHelperSvc,
const int  channelTypes,
double  meanGasGain,
bool  doPadChargeSharing,
double  stripChargeScale 
)

Definition at line 34 of file sTgcDigitMaker.cxx.

39  : AthMessaging ("sTgcDigitMaker"),
40  m_idHelperSvc{idHelperSvc},
41  m_channelTypes{channelTypes},
42  m_meanGasGain{meanGasGain},
43  m_doPadSharing{doPadChargeSharing},
44  m_stripChargeScale{stripChargeScale} {}

◆ ~sTgcDigitMaker()

sTgcDigitMaker::~sTgcDigitMaker ( )
virtualdefault

Member Function Documentation

◆ addDigit()

void sTgcDigitMaker::addDigit ( sTgcDigitVec digits,
const Identifier id,
const uint16_t  bctag,
const double  digittime,
const double  charge 
)
staticprivate

Definition at line 729 of file sTgcDigitMaker.cxx.

733  {
734 
735  constexpr double tolerance = 0.1;
736  if (std::find_if(digits.begin(),digits.end(), [&](std::unique_ptr<sTgcDigit>& known) {
737  return known->identify() == id && std::abs(digittime - known->time()) < tolerance;
738  }) == digits.end()) {
739  digits.push_back(std::make_unique<sTgcDigit>(id, bctag, digittime, charge, 0, 0));
740  }
741 }

◆ executeDigi()

sTgcDigitMaker::sTgcDigitVec sTgcDigitMaker::executeDigi ( const DigiConditions condContainers,
const sTGCSimHit hit 
) const

Definition at line 70 of file sTgcDigitMaker.cxx.

71  {
72  // SimHits without energy loss are not recorded.
73  double energyDeposit = hit.depositEnergy(); // Energy deposit in MeV
74  if(energyDeposit==0.) return {};
75 
77  const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
78  sTgcSimIdToOfflineId simToOffline{&idHelper};
79  const Identifier offlineId = simToOffline.convert(hit.sTGCId());
80  const Identifier layid = idHelper.channelID(offlineId,
81  idHelper.multilayer(offlineId),
82  idHelper.gasGap(offlineId),
83  sTgcIdHelper::sTgcChannelTypes::Wire, 1);
84 
85  ATH_MSG_VERBOSE("sTgc hit: time " << hit.globalTime()
86  << " position " << Amg::toString(hit.globalPosition(), 2)
87  << " mclink " << hit.particleLink() << " PDG ID " << hit.particleEncoding() );
88 
89 
90  ATH_MSG_DEBUG("Retrieving detector element for: "<< m_idHelperSvc->toStringDetEl(layid) << " energyDeposit "<<energyDeposit );
91 
92  const MuonGM::sTgcReadoutElement* detEl = condContainers.detMgr->getsTgcReadoutElement(layid);
93  if( !detEl ){ return {}; }
94 
95 
96  // DO THE DIGITIZATTION HERE ////////
97 
98  // Required precision on length in mm
99  constexpr double length_tolerance = 0.01;
100 
101  // Retrieve the wire surface
102  int surfHash_wire = detEl->surfaceHash(layid);
103  const Trk::PlaneSurface& SURF_WIRE = detEl->surface(surfHash_wire); // get the wire surface
104 
105  // Hit post-Step global position
106  const Amg::Vector3D& GPOS{hit.globalPosition()};
107  // Hit pre-Step global position
108  const Amg::Vector3D& pre_pos{hit.globalPrePosition()};
109  // Hit global direction
110  const Amg::Vector3D& GLODIRE{hit.globalDirection()};
111 
112  // Hit position in the wire surface's coordinate frame
113  Amg::Vector3D hitOnSurface_wire{SURF_WIRE.transform().inverse() * GPOS};
114  Amg::Vector3D pre_pos_wire_surf{SURF_WIRE.transform().inverse() * pre_pos};
115  Amg::Vector2D posOnSurf_wire{0.5 * (hitOnSurface_wire + pre_pos_wire_surf).block<2,1>(0,0)};
116 
117  /* Determine the closest wire and the distance of closest approach
118  * Since most particles pass through the the wire plane between two wires,
119  * the nearest wire should be one of these two wire. Otherwise, the particle's
120  * trajectory is uncommon, and such rare case is not supported yet.
121  *
122  * Finding that nearest wire follows the following steps:
123  * - Compute the distance to the wire at the center of the current wire pitch
124  * - Compute the distance to the other adjacent wire
125  */
126 
127  // Wire number of the current wire pitch
128  int wire_number = detEl->getDesign(layid)->wireNumber(posOnSurf_wire);
129 
130  // If wire number is invalid, verify if hit is near the edge of the chamber.
131  const int number_wires = detEl->numberOfWires(layid);
132  if ((wire_number < 1) || (wire_number > number_wires)) {
133  // Compute the wire number using either the pos-step position or
134  // the pre-step position, whichever yields a valid wire number.
135  wire_number = detEl->getDesign(layid)->wireNumber(hitOnSurface_wire.block<2,1>(0,0));
136  if ((wire_number < 1) || (wire_number > number_wires)) {
137  wire_number = detEl->getDesign(layid)->wireNumber(pre_pos_wire_surf.block<2,1>(0,0));
138  }
139  }
140 
141  // Compute the position of the ionization and its distance relative to a given sTGC wire.
142  Ionization ionization = pointClosestApproach(detEl, layid, wire_number, pre_pos_wire_surf, hitOnSurface_wire);
143  double dist_wire = ionization.distance;
144  if (dist_wire > 0.) {
145  // Determine the other adjacent wire, which is
146  // -1 if particle crosses the wire surface between wire_number-1 and wire_number
147  // +1 if particle crosses the wire surface between wire_number and wire_number+1
148  int adjacent = 1;
149  if (ionization.posOnSegment.x() < ionization.posOnWire.x()) {adjacent = -1;}
150 
151  // Find the position of the ionization with respect to the adjacent wire
152  Ionization ion_adj = pointClosestApproach(detEl, layid, wire_number+adjacent, pre_pos_wire_surf, hitOnSurface_wire);
153  // Keep the closest point
154  double dist_wire_adj = ion_adj.distance;
155  if ((dist_wire_adj > 0.) && (dist_wire_adj < dist_wire)) {
156  dist_wire = dist_wire_adj;
157  wire_number += adjacent;
158  ionization = std::move(ion_adj);
159  }
160  } else {
161  ATH_MSG_DEBUG("Failed to get the distance between the wire number = " << wire_number
162  << " and hit at " <<Amg::toString(hitOnSurface_wire, 2)
163  << ". Number of wires = " << number_wires
164  << ", "<<m_idHelperSvc->toStringGasGap(layid));
165  return {};
166  }
167 
168  // Update the position of ionization on the wire surface
169  posOnSurf_wire = ionization.posOnWire.block<2,1>(0,0);
170  // Position of the ionization in the global coordinate frame
171  const Amg::Vector3D glob_ionization_pos = SURF_WIRE.transform() * ionization.posOnWire;
172 
173  ATH_MSG_VERBOSE("Ionization_info: distance: " << ionization.distance
174  << " posOnTrack: " <<Amg::toString(ionization.posOnSegment, 3)
175  << " posOnWire: " << Amg::toString(ionization.posOnWire, 3)
176  << " hitGPos: " << Amg::toString(GPOS,3)
177  << " hitPrePos: " <<Amg::toString(pre_pos, 3)
178  << " EDep: " << hit.depositEnergy() << " EKin: " << hit.kineticEnergy()
179  << " pdgId: " << hit.particleEncoding()
180  <<" "<<m_idHelperSvc->toStringGasGap(layid));
181 
182  // Distance should be in the range [0, 0.9] mm, excepting
183  // - particles pass through the wire plane near the edges
184  // - secondary particles created inside the gas gap that go through the gas gap partially.
185  // Most of such particles are not muons and have low kinetic energy.
186  // - particle with trajectory parallel to the sTGC wire plane
187  const double wire_pitch = detEl->wirePitch();
188  if ((dist_wire > 0.) && (std::abs(hit.particleEncoding()) == 13) && (dist_wire > (wire_pitch/2))) {
189  ATH_MSG_DEBUG("Distance to the nearest wire (" << dist_wire << ") is greater than expected.");
190  ATH_MSG_DEBUG("Hit globalPos: "<<Amg::toString(GPOS,2)
191  << " globalPrePos: " << Amg::toString(pre_pos, 2)
192  << " EDeposited: " << hit.depositEnergy()
193  << " EKinetic: " << hit.kineticEnergy()
194  << " pdgID: " << hit.particleEncoding()
195  << " "<<m_idHelperSvc->toStringGasGap(layid));
196  }
197 
198  // Do not digitize hits that are too far from the nearest wire
199  if (dist_wire > wire_pitch) {
200  return {};
201  }
202 
203  // Get the gamma pdf parameters associated with the distance of closest approach.
204  const GammaParameter gamParam = getGammaParameter(dist_wire);
205  const double par_kappa = gamParam.kParameter;
206  const double par_theta = gamParam.thetaParameter;
207  const double most_prob_time = getMostProbableArrivalTime(dist_wire);
208  // Compute the most probable value of the gamma pdf
209  double gamma_mpv = (par_kappa - 1) * par_theta;
210  // If the most probable value is less than zero, then set it to zero
211  if (gamma_mpv < 0.) {gamma_mpv = 0.;}
212  const double t0_par = most_prob_time - gamma_mpv;
213 
214  // Digit time follows a gamma distribution, so a value val is
215  // chosen using a gamma random generator then is shifted by t0
216  // to account for drift time.
217  // Note: CLHEP::RandGamma takes the parameters k and lambda,
218  // where lambda = 1 / theta.
219  double digit_time = t0_par + CLHEP::RandGamma::shoot(condContainers.rndmEngine, par_kappa, 1/par_theta);
220 
221  // Sometimes, digit_time is negative because t0_par can be negative.
222  // In such case, discard the negative value and shoot RandGamma for another value.
223  // However, if that has already been done many times then set digit_time to zero
224  // in order to avoid runaway loop.
225  constexpr int shoot_limit = 4;
226  int shoot_counter = 0;
227  while (digit_time < 0.) {
228  if (shoot_counter > shoot_limit) {
229  digit_time = 0.;
230  break;
231  }
232  digit_time = t0_par + CLHEP::RandGamma::shoot(condContainers.rndmEngine, par_kappa, 1/par_theta);
233  ++shoot_counter;
234  }
235 
236  ATH_MSG_DEBUG("sTgcDigitMaker distance = " << dist_wire
237  << ", time = " << digit_time
238  << ", k parameter = " << par_kappa
239  << ", theta parameter = " << par_theta
240  << ", most probable time = " << most_prob_time);
241 
242  bool isValid = false;
244  if (condContainers.efficiencies) {
245  const double efficiency = condContainers.efficiencies->getEfficiency(layid);
246  // Lose Hits to match HV efficiency
247  if (CLHEP::RandFlat::shoot(condContainers.rndmEngine,0.0,1.0) > efficiency) return {};
248  }
249 
250 
251  sTgcDigitVec digits{};
252 
253  //const double stripPropagationTime = 3.3*CLHEP::ns/CLHEP::m * detEl->distanceToReadout(posOnSurf_strip, elemId); // 8.5*ns/m was used until MC10.
254  const double stripPropagationTime = 0.; // 8.5*ns/m was used until MC10.
255 
256  double sDigitTimeWire = digit_time;
257  double sDigitTimePad = sDigitTimeWire;
258  double sDigitTimeStrip = sDigitTimeWire + stripPropagationTime;
259 
260  uint16_t bctag = 0;
261 
262  //##################################################################################
263  //######################################### strip readout ##########################
264  //##################################################################################
265  ATH_MSG_DEBUG("sTgcDigitMaker::strip response ");
266  int channelType = sTgcIdHelper::sTgcChannelTypes::Strip;
267 
268  Identifier newId = idHelper.channelID(layid,idHelper.multilayer(layid),
269  idHelper.gasGap(layid), channelType, 1, isValid);
270 
271  // get strip surface
272  int surfHash_strip = detEl->surfaceHash(newId);
273  const Trk::PlaneSurface& SURF_STRIP = detEl->surface(surfHash_strip); // get the strip surface
274 
275  const Amg::Vector3D hitOnSurface_strip = SURF_STRIP.transform().inverse()*glob_ionization_pos;
276 
277  const Amg::Vector2D posOnSurf_strip(hitOnSurface_strip.x(),hitOnSurface_strip.y());
278  bool insideBounds = SURF_STRIP.insideBounds(posOnSurf_strip);
279  if(!insideBounds) {
280  ATH_MSG_DEBUG("Outside of the strip surface boundary : " << m_idHelperSvc->toString(newId) << "; local position " <<posOnSurf_strip );
281  return {};
282  }
283 
284  //************************************ find the nearest readout element **************************************
285 
286  int stripNumber = detEl->stripNumber(posOnSurf_strip, newId);
287  if( stripNumber == -1 ){
288  // Verify if the energy deposit is at the boundary
289  const double new_posX = (posOnSurf_strip.x() > 0.0)? posOnSurf_strip.x() - length_tolerance
290  : posOnSurf_strip.x() + length_tolerance;
291  const Amg::Vector2D new_position(new_posX, posOnSurf_strip.y());
292  stripNumber = detEl->stripNumber(new_position, newId);
293  // Skip hit if still unable to obtain strip number
294  if (stripNumber < 1) {
295  ATH_MSG_WARNING("Failed to obtain strip number " << m_idHelperSvc->toString(newId) );
296  ATH_MSG_WARNING("Position on strip surface = (" << posOnSurf_strip.x() << ", " << posOnSurf_strip.y() << ")");
297  return {};
298  }
299  }
300  newId = idHelper.channelID(layid, idHelper.multilayer(layid),
301  idHelper.gasGap(layid), channelType, stripNumber, isValid);
302  if(!isValid && stripNumber != -1) {
303  ATH_MSG_ERROR("Failed to obtain identifier " << m_idHelperSvc->toString(newId) );
304  return {};
305  }
306 
307  const int NumberOfStrips = detEl->numberOfStrips(newId);
308  const double stripHalfPitch = detEl->channelPitch(newId)*0.5; // 3.2/2 = 1.6 mm
309 
310  //************************************ conversion of energy to charge **************************************
311 
312  // Typical ionized charge in pC per keV deposited. The constant is determined from ionization
313  // study with Garfield program. A note titled "Charge Energy Relation" which outlines
314  // conversion can be found here:
315  // https://cernbox.cern.ch/index.php/apps/files/?dir=/__myshares/Documents (id:274113) // link is dead
316  const double ionized_charge = (5.65E-6)*energyDeposit/CLHEP::keV;
317 
318  // To get avalanche gain, polya function is taken from Blum paper https://inspirehep.net/literature/807304
319  // m_polyaFunction = new TF1("m_polyaFunction","(1.0/[1])*(TMath::Power([0]+1,[0]+1)/TMath::Gamma([0]+1))*TMath::Power(x/[1],[0])*TMath::Exp(-([0]+1)*x/[1])",0,3000000);
320 
321  // Mean value for total gain due to E field;
322  // To calculate this gain from polya distibution, we replace in gamma PDF:
323  // alpha = 1+theta and
324  // beta = 1+theta/mean
325  // With these substitutions, gamma PDF gives the same sampling values as those from polya PDF.
326  const double gain = CLHEP::RandGamma::shoot(condContainers.rndmEngine, 1. + m_theta, (1. + m_theta)/m_meanGasGain);
327 
328  // total charge after avalanche
329  const double total_charge = gain*ionized_charge;
330 
331  //************************************ spread charge among readout element **************************************
332 
333  // Charge Spread including tan(theta) resolution term.
334  const double tan_theta = GLODIRE.perp()/GLODIRE.z();
335  // The angle dependance on strip resolution goes as tan^2(angle)
336  const double angle_dependency = std::hypot(m_posResIncident, m_posResAngular * tan_theta);
337 
338  const double cluster_posX = posOnSurf_strip.x();
339  double peak_position = CLHEP::RandGaussZiggurat::shoot(condContainers.rndmEngine, cluster_posX, m_StripResolution*angle_dependency);
340 
341  // Each readout plane reads about half the total charge produced on the wire,
342  // including a tan(theta) term to describe the increase of charge with incident angle
343  const double norm = 0.5 * total_charge * m_stripChargeScale * std::hypot(1, m_chargeAngularFactor * tan_theta);
344  // Strip cluster charge profile described by a double Gaussian.
345  // The independent parameter x is in the units of strip channel, one strip channel = 3.2 mm,
346  // so convert position from mm to strip channel if it is not already.
347  std::unique_ptr<TF1> clusterProfile = std::make_unique<TF1>("fgaus",
348  "[0]*exp(-0.5*(x/[1])^2)+[2]*exp(-0.5*(x/[3])^2)",
349  -300., 300.);
350  clusterProfile->SetParameters(norm * m_clusterProfile[0], // normalization of 1st Gaussian
351  m_clusterProfile[1], // sigma of 1st Gaussian
352  norm * m_clusterProfile[2], // normalization of 2nd Gaussian
353  m_clusterProfile[3]); // sigma of 2nd Gaussian
354 
355  // Lower limit on strip charge (arbitrary limit), in pC, which has the same units as the parameter ionized_charge.
356  constexpr double tolerance_charge = 0.0005;
357  // Set a maximum number of neighbour strips to avoid very long loop. This is an arbitrary number.
358  constexpr unsigned int max_neighbor = 10;
359 
360  // Spread charge on the strips that are on the upper half of the strip cluster
361  for (unsigned int iStrip = 0; iStrip <= max_neighbor; ++iStrip) {
362  int currentStrip = stripNumber + iStrip;
363  if (currentStrip > NumberOfStrips) break;
364 
365  // Get the strip identifier and create the digit
366  newId = idHelper.channelID(layid, idHelper.multilayer(layid), idHelper.gasGap(layid),
367  channelType, currentStrip, isValid);
368  if (isValid) {
370  if (!detEl->stripPosition(newId, locpos)) {
371  ATH_MSG_WARNING("Failed to obtain local position for identifier " << m_idHelperSvc->toString(newId) );
372  }
373 
374  // Estimate the digit charge
375  // Position with respect to the peak of the charge curve
376  double x_relative = locpos.x() - peak_position;
377  // In clusterProfile curve, position should be in the units of strip channel
378  double charge = clusterProfile->Integral(x_relative/(2*stripHalfPitch) - 0.5, x_relative/(2*stripHalfPitch) + 0.5);
379  // If charge is too small, stop creating neighbor strip
380  if (charge < tolerance_charge) break;
381 
382  // Estimate digit time
383  double strip_time = sDigitTimeStrip;
384  // Strip time response can be delayed due to the resistive layer.
385  // A correction would be required if the actual VMM front-end doesn't re-align the strip timing.
386  if (m_doTimeOffsetStrip) {
387  // Determine how far the current strip is from the middle strip
388  int indexFromMiddleStrip = iStrip;
389  if ((iStrip > 0) && ((x_relative + (0.75 - iStrip * 2) * stripHalfPitch) < 0))
390  indexFromMiddleStrip = iStrip - 1;
391  // Add time delay due to resistive layer
392  strip_time += getTimeOffsetStrip(indexFromMiddleStrip);
393  }
394 
395  addDigit(digits, newId, bctag, strip_time, charge);
396 
397  ATH_MSG_VERBOSE("Created a strip digit: strip number = " << currentStrip << ", charge = " << charge
398  << ", time = " << strip_time << ", time offset = " << strip_time-sDigitTimeStrip
399  << ", neighbor index = " << iStrip
400  << ", strip position = "<<Amg::toString(locpos, 2));
401  }
402  }
403 
404  // The lower half of the strip cluster
405  for (unsigned int iStrip = 1; iStrip <= max_neighbor; ++iStrip) {
406  int currentStrip = stripNumber - iStrip;
407  if (currentStrip < 1) break;
408 
409  newId = idHelper.channelID(layid,idHelper.multilayer(layid),
410  idHelper.gasGap(layid), channelType, currentStrip, isValid);
411  if (isValid) {
413  if (!detEl->stripPosition(newId, locpos)) {
414  ATH_MSG_WARNING("Failed to obtain local position for identifier " << m_idHelperSvc->toString(newId) );
415  }
416 
417  // Estimate the digit charge
418  double x_relative = locpos.x() - peak_position;
419  double charge = clusterProfile->Integral(x_relative/(2*stripHalfPitch) - 0.5, x_relative/(2*stripHalfPitch) + 0.5);
420  if (charge < tolerance_charge) break;
421 
422  // Estimate digit time
423  double strip_time = sDigitTimeStrip;
424  // Time delay due to resistive layer
425  if (m_doTimeOffsetStrip) {
426  int indexFromMiddleStrip = ((x_relative + (iStrip * 2 - 0.75) * stripHalfPitch) > 0)? iStrip - 1 : iStrip;
427  strip_time += getTimeOffsetStrip(indexFromMiddleStrip);
428  }
429 
430  addDigit(digits, newId, bctag, strip_time, charge);
431 
432  ATH_MSG_VERBOSE("Created a strip digit: strip number = " << currentStrip << ", charge = " << charge
433  << ", time = " << strip_time << ", time offset = " << strip_time-sDigitTimeStrip
434  << ", neighbor index = " << iStrip
435  << ", strip position = " << Amg::toString(locpos, 2));
436  }
437  }
438  // end of strip digitization
439 
440  if(m_channelTypes==1) {
441  ATH_MSG_WARNING("Only digitize strip response !");
442  return digits;
443  }
444 
445  //##################################################################################
446  //######################################### pad readout ##########################
447  //##################################################################################
448  ATH_MSG_DEBUG("sTgcDigitMaker::pad response ");
449  channelType = sTgcIdHelper::sTgcChannelTypes::Pad;
450 
451  Identifier PAD_ID = idHelper.channelID(layid, idHelper.multilayer(layid),
452  idHelper.gasGap(layid), channelType, 1);// find the a pad id
453  //************************************ find the nearest readout element **************************************
454  int surfHash_pad = detEl->surfaceHash(PAD_ID);
455  const Trk::PlaneSurface& SURF_PAD = detEl->surface(surfHash_pad); // get the pad surface
456 
457  const Amg::Vector3D hitOnSurface_pad = SURF_PAD.transform().inverse()*glob_ionization_pos;
458  const Amg::Vector2D posOnSurf_pad(hitOnSurface_pad.x(), hitOnSurface_pad.y());
459 
460 
461  insideBounds = SURF_PAD.insideBounds(posOnSurf_pad);
462 
463  if(insideBounds) {
464  int padNumber = detEl->stripNumber(posOnSurf_pad, PAD_ID);
465  if( padNumber == -1 ){
466  // Verify if the energy deposit is at the boundary
467  const double new_posX = (posOnSurf_pad.x()>0.0)? posOnSurf_pad.x()-length_tolerance
468  : posOnSurf_pad.x()+length_tolerance;
469  const double new_posY = (posOnSurf_pad.y()>0.0)? posOnSurf_pad.y()-length_tolerance
470  : posOnSurf_pad.y()+length_tolerance;
471  const Amg::Vector2D new_position(new_posX, new_posY);
472  padNumber = detEl->stripNumber(new_position, PAD_ID);
473  // Skip hit if still unable to obtain pad number
474  if (padNumber < 1) {
475  ATH_MSG_WARNING("Failed to obtain pad number " << m_idHelperSvc->toString(PAD_ID) );
476  ATH_MSG_WARNING("Position on pad surface = (" << posOnSurf_pad.x() << ", " << posOnSurf_pad.y() << ")");
477  return digits;
478  }
479  }
480  newId = idHelper.channelID(layid, idHelper.multilayer(layid),
481  idHelper.gasGap(layid), channelType, padNumber, isValid);
482  if(isValid) {
483  // Find centre position of pad
485  if (!detEl->stripPosition(newId, padPos)) {
486  ATH_MSG_ERROR("Failed to obtain local position for neighbor pad with identifier " << m_idHelperSvc->toString(newId) );
487  return digits;
488  }
489  // Pad sharing needs to look at position on hit vs pad boundaries
490  const Amg::Vector2D diff = posOnSurf_pad - padPos;
491  double halfPadWidthX = 0.5*detEl->getPadDesign(newId)->channelWidth(posOnSurf_pad, true, true);
492  double halfPadWidthY = 0.5*detEl->getPadDesign(newId)->channelWidth(posOnSurf_pad, false);
493 
494  // Charge sharing happens within 4mm window for pads
495  // i.e. the charge is spread over a 2D gaussian of total radius about 4mm
496  // This value depends on actual width of the distribution, but we don't have the
497  // width of the charge distribution for pads. So lets consider 2.5*sigma, where
498  // sigma is the width of the charge distribution for strips.
499  double deltaX = halfPadWidthX - std::abs(diff.x());
500  double deltaY= halfPadWidthY - std::abs(diff.y());
501  bool isNeighX = deltaX < 2.5*m_clusterProfile[3];
502  bool isNeighY = deltaY < 2.5*m_clusterProfile[3];
503  // Pad width can be calculated to be very slightly larger than it should due to rounding errors
504  // So if a hit falls on a given pad but is "outside" the width, just define it to be on the boundary of 2 pads.
505  if (deltaX < 0.) deltaX = 0.1;
506  if (deltaY < 0.) deltaY = 0.1;
507 
508  if (m_doPadSharing && (isNeighX || isNeighY)){
509  std::pair<int, int> padEtaPhi(detEl->getPadDesign(newId)->channelNumber(padPos));
510  // Phi == 1 at the right in the local geometry
511  // In local coordinates, the pad to the right has phi' = phi - 1
512  int newPhi = diff.x() > 0 ? padEtaPhi.second-1 : padEtaPhi.second+1;
513  int newEta = diff.y() > 0 ? padEtaPhi.first+1 : padEtaPhi.first-1;
514  bool validEta = newEta > 0 && newEta < detEl->getPadDesign(newId)->nPadH+1;
515  bool validPhi = newPhi > 0 && newPhi < detEl->getPadDesign(newId)->nPadColumns+1;
516 
517  if (isNeighX && isNeighY && validEta && validPhi){
518  // 4 pads total; makes life a bit harder. Corner of 4 valid pads
519  Identifier neigh_ID_X = idHelper.padID(newId, idHelper.multilayer(newId), idHelper.gasGap(newId),
520  channelType, padEtaPhi.first, newPhi, isValid);
521  Identifier neigh_ID_Y = idHelper.padID(newId, idHelper.multilayer(newId), idHelper.gasGap(newId),
522  channelType, newEta, padEtaPhi.second, isValid);
523  Identifier neigh_ID_XY = idHelper.padID(newId, idHelper.multilayer(newId), idHelper.gasGap(newId),
524  channelType, newEta, newPhi, isValid);
525  double xQfraction = getPadChargeFraction(deltaX);
526  double yQfraction = getPadChargeFraction(deltaY);
527 
528  // Main pad gets 1 - Qfraction of total
529  addDigit(digits, neigh_ID_X, bctag, sDigitTimePad, xQfraction*(1.-yQfraction)*0.5*total_charge);
530  addDigit(digits, neigh_ID_Y, bctag, sDigitTimePad, yQfraction*(1.-xQfraction)*0.5*total_charge);
531  addDigit(digits, neigh_ID_XY, bctag, sDigitTimePad, xQfraction*yQfraction*0.5*total_charge);
532  addDigit(digits, newId, bctag, sDigitTimePad, (1.-xQfraction-yQfraction+xQfraction*yQfraction)*0.5*total_charge);
533  } else if (isNeighX && validPhi){
534  // There is only 1 neighbor, immediately to the left or right.
535  Identifier neigh_ID = idHelper.padID(newId, idHelper.multilayer(newId), idHelper.gasGap(newId),
536  channelType, padEtaPhi.first, newPhi, isValid);
537 
538  // NeighborPad gets Qfraction of the total pad charge: 0.5*total_charge
539  // Main pad gets 1 - Qfraction of total
540  double xQfraction = getPadChargeFraction(deltaX);
541  addDigit(digits, newId, bctag, sDigitTimePad, (1.-xQfraction)*0.5*total_charge);
542  addDigit(digits, neigh_ID, bctag, sDigitTimePad, xQfraction*0.5*total_charge);
543  }
544  else if (isNeighY && validEta){
545  // There is only 1 neighbor, immediately above or below
546  Identifier neigh_ID = idHelper.padID(newId, idHelper.multilayer(newId), idHelper.gasGap(newId),
547  channelType, newEta, padEtaPhi.second, isValid);
548 
549  // NeighborPad gets Qfraction of the total pad charge: 0.5*total_charge
550  // Main pad gets 1 - Qfraction of total
551  double yQfraction = getPadChargeFraction(deltaX);
552  addDigit(digits, newId, bctag, sDigitTimePad, (1.-yQfraction)*0.5*total_charge);
553  addDigit(digits, neigh_ID, bctag, sDigitTimePad, yQfraction*0.5*total_charge);
554  }
555 
556  }
557  else{
558  // No charge sharing: hit is nicely isolated within pad
559  addDigit(digits, newId, bctag, sDigitTimePad, 0.5*total_charge);
560  }
561 
562  }
563  else if(padNumber != -1) {
564  ATH_MSG_ERROR("Failed to obtain identifier " << m_idHelperSvc->toString(newId) );
565  }
566  }
567  else {
568  ATH_MSG_DEBUG("Outside of the pad surface boundary :" << m_idHelperSvc->toString(PAD_ID)<< " local position " <<posOnSurf_pad );
569  }
570 
571  if(m_channelTypes==2) {
572  ATH_MSG_WARNING("Only digitize strip/pad response !");
573  return digits;
574  }
575 
576 
577  //##################################################################################
578  //######################################### wire readout ##########################
579  //##################################################################################
580  ATH_MSG_DEBUG("sTgcDigitMaker::wire response ");
581  channelType = sTgcIdHelper::sTgcChannelTypes::Wire;
582 
583  // Find the ID of the first wiregroup
584  Identifier WIREGP_ID = idHelper.channelID(layid, idHelper.multilayer(layid),
585  idHelper.gasGap(layid), channelType, 1);
586 
587  //************************************ find the nearest readout element **************************************
588  insideBounds = SURF_WIRE.insideBounds(posOnSurf_wire);
589 
590  if(insideBounds) {
591  // Determine the wire number
592 
593  int wiregroupNumber = detEl->stripNumber(posOnSurf_wire, WIREGP_ID);
594  if( wiregroupNumber == -1 ){
595  // Verify if the energy deposit is at the boundary
596  const double new_posX = (posOnSurf_wire.x() > 0.0)? posOnSurf_wire.x() - length_tolerance
597  : posOnSurf_wire.x() + length_tolerance;
598  const Amg::Vector2D new_position(new_posX, posOnSurf_wire.y());
599  wiregroupNumber = detEl->stripNumber(new_position, WIREGP_ID);
600  // Skip hit if still unable to obtain pad number
601  if (wiregroupNumber < 1) {
602  ATH_MSG_WARNING("Failed to obtain wire number " << m_idHelperSvc->toString(WIREGP_ID) );
603  ATH_MSG_WARNING("Position on wire surface = (" << posOnSurf_wire.x() << ", " << posOnSurf_wire.y() << ")");
604  return digits;
605  }
606  }
607 
608  // Find ID of the actual wiregroup
609  newId = idHelper.channelID(layid, idHelper.multilayer(layid), idHelper.gasGap(layid),
610  channelType, wiregroupNumber, isValid);
611 
612  if(isValid) {
613  int NumberOfWiregroups = detEl->numberOfStrips(newId);
614  if(wiregroupNumber>=1&&wiregroupNumber<=NumberOfWiregroups) {
615  addDigit(digits, newId, bctag, sDigitTimeWire, total_charge);
616  }
617  } // end of if(isValid)
618  else if (wiregroupNumber != -1){
619  ATH_MSG_ERROR("Failed to obtain wiregroup identifier " << m_idHelperSvc->toString(newId) );
620  }
621  }
622  else {
623  ATH_MSG_DEBUG("Outside of the wire surface boundary :" << m_idHelperSvc->toString(WIREGP_ID)<< " local position " <<posOnSurf_wire );
624  }
625  // end of wire digitization
626 
627  return digits;
628 }

◆ getGammaParameter()

sTgcDigitMaker::GammaParameter sTgcDigitMaker::getGammaParameter ( double  distance) const
private

Find the gamma pdf parameters of a given distance.

Definition at line 784 of file sTgcDigitMaker.cxx.

784  {
785 
786  const double d = std::abs(distance);
787  // Find the parameters assuming the container is sorted in ascending order of 'lowEdge'
788  int index{-1};
789  for (const auto& par: m_gammaParameter) {
790  if (d < par.lowEdge) {
791  break;
792  }
793  ++index;
794  }
795  return m_gammaParameter.at(index);
796 }

◆ getMostProbableArrivalTime()

double sTgcDigitMaker::getMostProbableArrivalTime ( double  distance) const
private

Get the most probable time of arrival.

Definition at line 799 of file sTgcDigitMaker.cxx.

799  {
800 
801  const double d{std::abs(distance)};
802  double mpt{0};
803  for (size_t t = 0 ; t < m_mostProbableArrivalTime.size(); ++t){
804  mpt += m_mostProbableArrivalTime[t] * std::pow(d, t);
805  }
806  return mpt;
807 }

◆ getPadChargeFraction()

double sTgcDigitMaker::getPadChargeFraction ( double  distance)
staticprivate

Definition at line 854 of file sTgcDigitMaker.cxx.

854  {
855  // The charge fraction that is found past a distance x away from the
856  // centre of a 2D gaussian distribution of width of cluster profile is
857  // described by a modified error function.
858 
859  // The modified error function perfectly describes
860  // the pad charge sharing distribution figure 16 of the sTGC
861  // testbeam paper https://arxiv.org/pdf/1509.06329.pdf
862 
863  return 0.5 * (1.0 - std::erf( distance / (std::sqrt(2) * m_clusterProfile[3])));
864 }

◆ getTimeOffsetStrip()

double sTgcDigitMaker::getTimeOffsetStrip ( size_t  neighbor_index) const
private

Get digit time offset of a strip depending on its relative position to the strip at the centre of the cluster.

It returns 0 ns by default, as well as when it fails or container is empty.

Definition at line 849 of file sTgcDigitMaker.cxx.

849  {
850  return m_timeOffsetStrip.at(std::min(neighbor_index, m_timeOffsetStrip.size() -1));
851 }

◆ initialize()

StatusCode sTgcDigitMaker::initialize ( )

Initializes sTgcHitIdHelper and sTgcIdHelper, and call the functions to read files containing digitization parameters.

Definition at line 50 of file sTgcDigitMaker.cxx.

50  {
51 
52  // Read share/sTGC_Digitization_timeArrivale.dat, containing the digit time of arrival
54 
55  // Read share/sTGC_Digitization_timeOffsetStrip.dat if the the strip time correction is enable
56  if (m_doTimeOffsetStrip) {
58  }
59  // check the digitization channel type
60  if(m_channelTypes!=1 && m_channelTypes!=2 && m_channelTypes!=3) {
61  ATH_MSG_ERROR("Invalid ChannelTypes : " << m_channelTypes << " (valid values are : 1 --> strips ; 2 --> strips / wires ; 3 --> strips / wires / pads)");
62  return StatusCode::FAILURE;
63  }
64  return StatusCode::SUCCESS;
65 }

◆ initMessaging()

void AthMessaging::initMessaging ( ) const
privateinherited

Initialize our message level and MessageSvc.

This method should only be called once.

Definition at line 39 of file AthMessaging.cxx.

40 {
42  m_lvl = m_imsg ?
43  static_cast<MSG::Level>( m_imsg.load()->outputLevel(m_nm) ) :
44  MSG::INFO;
45 }

◆ msg() [1/2]

MsgStream & AthMessaging::msg ( ) const
inlineinherited

The standard message stream.

Returns a reference to the default message stream May not be invoked before sysInitialize() has been invoked.

Definition at line 164 of file AthMessaging.h.

165 {
166  MsgStream* ms = m_msg_tls.get();
167  if (!ms) {
168  if (!m_initialized.test_and_set()) initMessaging();
169  ms = new MsgStream(m_imsg,m_nm);
170  m_msg_tls.reset( ms );
171  }
172 
173  ms->setLevel (m_lvl);
174  return *ms;
175 }

◆ msg() [2/2]

MsgStream & AthMessaging::msg ( const MSG::Level  lvl) const
inlineinherited

The standard message stream.

Returns a reference to the default message stream May not be invoked before sysInitialize() has been invoked.

Definition at line 179 of file AthMessaging.h.

180 { return msg() << lvl; }

◆ msgLvl()

bool AthMessaging::msgLvl ( const MSG::Level  lvl) const
inlineinherited

Test the output level.

Parameters
lvlThe message level to test against
Returns
boolean Indicating if messages at given level will be printed
Return values
trueMessages at level "lvl" will be printed

Definition at line 151 of file AthMessaging.h.

152 {
153  if (!m_initialized.test_and_set()) initMessaging();
154  if (m_lvl <= lvl) {
155  msg() << lvl;
156  return true;
157  } else {
158  return false;
159  }
160 }

◆ pointClosestApproach()

sTgcDigitMaker::Ionization sTgcDigitMaker::pointClosestApproach ( const MuonGM::sTgcReadoutElement readoutEle,
const Identifier id,
int  wireNumber,
const Amg::Vector3D preStepPos,
const Amg::Vector3D postStepPos 
) const
private

Determine the points where the distance between two segments is smallest.

Given two segments, e.g. a particle trajectory and a sTGC wire, solve for the two points, the point on the trajectory and the point on the wire, where the distance between the two segments is the smallest.

Positions returned are in the local coordinate frame of the wire plane. Returns an object with distance of -9.99 in case of error.

Definition at line 631 of file sTgcDigitMaker.cxx.

635  {
636  // tolerance in mm
637  constexpr double tolerance = 0.001;
638  // minimum segment length
639  constexpr double min_length = 0.1;
640 
641  // Position of the ionization
642  Ionization ionization;
643 
644  // Wire number should be one or greater
645  if (wireNumber < 1) return ionization;
646 
647  // Wire number too large
648  if (wireNumber > detEl->numberOfWires(id)) return ionization;
649 
650  // Finding smallest distance and the points at the smallest distance.
651  // The smallest distance between two lines is perpendicular to both lines.
652  // We can construct two lines in the wire surface local coordinate frame:
653  // - one for the hit segment with equation h0 + t * v_h, where h0 is a point
654  // and v_h is the unit vector of the hit segment
655  // - another for the wire with similar equation w0 + s * v_w, where w0 is a
656  // point and v_w is the unit vector of the wire line
657  // Then it is possible to determine the factors s and t by requiring the
658  // dot product to be zero:
659  // 1. (h0 - w0) \dot v_h = 0
660  // 2. (h0 - w0) \dot v_w = 0
661 
662  // Wire pitch
663  const double wire_pitch = detEl->wirePitch();
664  // Wire local position on the wire plane, the y-coordinate is arbitrary and z-coordinate is zero
665  const double wire_posX = detEl->positionFirstWire(id) + (wireNumber - 1) * wire_pitch;
666  const Amg::Vector3D wire_position(wire_posX, postStepPos.y(), 0.);
667  // The wires are parallel to Y in the wire plane's coordinate frame
668  const Amg::Vector3D wire_direction{Amg::Vector3D::UnitY()};
669 
670  // particle trajectory
671  Amg::Vector3D hit_direction{postStepPos - preStepPos};
672  const double seg_length = hit_direction.mag();
673  if (seg_length > tolerance) hit_direction /= seg_length;
674 
675  // Find the point on the track segment that is closest to the wire
676  if (seg_length < min_length) {
677  ionization.posOnSegment = postStepPos;
678  ionization.posOnWire = wire_position;
679  ionization.distance = std::hypot(postStepPos.x() - wire_posX, postStepPos.z());
680  return ionization;
681  }
682 
683  // Dot product between the wire and hit direction
684  const double cos_theta = wire_direction.dot(hit_direction);
685  // distance between the hit and wire
686  const Amg::Vector3D dist_wire_hit = postStepPos - wire_position;
687 
688  // Verifier the special case where the two lines are parallel
689  if (std::abs(cos_theta - 1.0) < tolerance) {
690  ATH_MSG_DEBUG("The track segment is parallel to the wire, position of digit is undefined");
691  ionization.posOnSegment = 0.5 * (postStepPos + preStepPos);
692  ionization.posOnWire = Amg::Vector3D(wire_posX, ionization.posOnSegment.y(), 0.0);
693  ionization.distance = std::hypot(ionization.posOnSegment.x() - wire_posX,
694  ionization.posOnSegment.z());
695  return ionization;
696  }
697 
698  // Perpendicular component squared
699  const double sin_theta_2 = 1.0 - cos_theta * cos_theta;
700 
701  //* Point on the hit segment
702  const double factor_hit = (-dist_wire_hit.dot(hit_direction)
703  + dist_wire_hit.dot(wire_direction) * cos_theta) / sin_theta_2;
704  Amg::Vector3D ionization_pos = postStepPos + factor_hit * hit_direction;
705 
706  // If the point is on the track segment, then compute the other point on the wire.
707  // Otherwise, set the ionization at the pre-step position and compute where it
708  // should be on the wire.
709  Amg::Vector3D pos_on_wire{Amg::Vector3D::Zero()};
710  if (factor_hit < seg_length) {
711  //* Point on the wire line
712  const double factor_wire = (dist_wire_hit.dot(wire_direction)
713  - dist_wire_hit.dot(hit_direction) * cos_theta) / sin_theta_2;
714  pos_on_wire = wire_position + factor_wire * wire_direction;
715  } else {
716  ionization_pos = preStepPos;
717  pos_on_wire = wire_position - (seg_length * cos_theta) * wire_direction;
718  }
719 
720  // Save the distance and ionization position
721  ionization.distance = (ionization_pos - pos_on_wire).mag();
722  ionization.posOnSegment = ionization_pos;
723  ionization.posOnWire = pos_on_wire;
724 
725  return ionization;
726 }

◆ readFileOfTimeArrival()

StatusCode sTgcDigitMaker::readFileOfTimeArrival ( )
private

Read share/sTGC_Digitization_timeArrival.dat.

Definition at line 744 of file sTgcDigitMaker.cxx.

744  {
745  // Verify the file sTGC_Digitization_timeArrival.dat exists
746  const std::string file_name = "sTGC_Digitization_timeArrival.dat";
747  std::string file_path = PathResolver::find_file(file_name, "DATAPATH");
748  if(file_path.empty()) {
749  ATH_MSG_FATAL("readFileOfTimeWindowOffset(): Could not find file " << file_name );
750  return StatusCode::FAILURE;
751  }
752 
753  // Open the sTGC_Digitization_timeArrival.dat file
754  std::ifstream ifs{file_path, std::ios::in};
755  if(ifs.bad()) {
756  ATH_MSG_FATAL("sTgcDigitMaker: Failed to open time of arrival file " << file_name );
757  return StatusCode::FAILURE;
758  }
759 
760  // Read the sTGC_Digitization_timeWindowOffset.dat file
761  std::string line;
762  GammaParameter param{};
763 
764  while (std::getline(ifs, line)) {
765  std::string key;
766  std::istringstream iss(line);
767  iss >> key;
768  if (key.compare("bin") == 0) {
769  iss >> param.lowEdge >> param.kParameter >> param.thetaParameter;
770  m_gammaParameter.push_back(param);
771  } else if (key.compare("mpv") == 0) {
772  double mpt;
773  int idx{0};
774  while (iss >> mpt) {m_mostProbableArrivalTime[idx++] = mpt;}
775  }
776  }
777 
778  // Close the file
779  ifs.close();
780  return StatusCode::SUCCESS;
781 }

◆ readFileOfTimeOffsetStrip()

StatusCode sTgcDigitMaker::readFileOfTimeOffsetStrip ( )
private

Read share/sTGC_Digitization_timeOffsetStrip.dat.

Definition at line 810 of file sTgcDigitMaker.cxx.

810  {
811  // Verify the file sTGC_Digitization_timeOffsetStrip.dat exists
812  const std::string file_name = "sTGC_Digitization_timeOffsetStrip.dat";
813  std::string file_path = PathResolver::find_file(file_name, "DATAPATH");
814  if(file_path.empty()) {
815  ATH_MSG_FATAL("readFileOfTimeWindowOffset(): Could not find file " << file_name );
816  return StatusCode::FAILURE;
817  }
818 
819  // Open the sTGC_Digitization_timeOffsetStrip.dat file
820  std::ifstream ifs{file_path, std::ios::in};
821  if(ifs.bad()) {
822  ATH_MSG_FATAL("Failed to open time of arrival file " << file_name );
823  return StatusCode::FAILURE;
824  }
825 
826  // Initialize the container to store the time offset.
827  // The number of parameters, 6, corresponds to the number of lines to be read
828  // from sTGC_Digitization_timeOffsetStrip.dat.
829  // Setting the default offset to 0 ns.
830 
831  // Read the input file
832  std::string line;
833  size_t index{0};
834  double value{0.0};
835  while (std::getline(ifs, line)) {
836  std::string key;
837  std::istringstream iss(line);
838  iss >> key;
839  if (key.compare("strip") == 0) {
840  iss >> index >> value;
841  if (index >= m_timeOffsetStrip.size()) continue;
843  }
844  }
845  return StatusCode::SUCCESS;
846 }

◆ setLevel()

void AthMessaging::setLevel ( MSG::Level  lvl)
inherited

Change the current logging level.

Use this rather than msg().setLevel() for proper operation with MT.

Definition at line 28 of file AthMessaging.cxx.

29 {
30  m_lvl = lvl;
31 }

Member Data Documentation

◆ ATLAS_THREAD_SAFE

std::atomic_flag m_initialized AthMessaging::ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT
mutableprivateinherited

Messaging initialized (initMessaging)

Definition at line 141 of file AthMessaging.h.

◆ m_channelTypes

int sTgcDigitMaker::m_channelTypes {3}
private

define offsets and widths of time windows for signals from wiregangs and strips.

The offsets are defined as relative time diffference with respect to the time after TOF and cable length corrections. Bunch crossing time is specified.

Definition at line 147 of file sTgcDigitMaker.h.

◆ m_chargeAngularFactor

double sTgcDigitMaker::m_chargeAngularFactor {4.0}
private

Definition at line 163 of file sTgcDigitMaker.h.

◆ m_clusterProfile

constexpr std::array<double, 4> sTgcDigitMaker::m_clusterProfile {0.350, 0.573, 0.186, 1.092}
staticconstexprprivate

Definition at line 161 of file sTgcDigitMaker.h.

◆ m_doPadSharing

bool sTgcDigitMaker::m_doPadSharing {false}
private

Definition at line 150 of file sTgcDigitMaker.h.

◆ m_doTimeOffsetStrip

bool sTgcDigitMaker::m_doTimeOffsetStrip {false}
private

Definition at line 154 of file sTgcDigitMaker.h.

◆ m_gammaParameter

std::vector<GammaParameter> sTgcDigitMaker::m_gammaParameter
private

Definition at line 131 of file sTgcDigitMaker.h.

◆ m_idHelperSvc

const Muon::IMuonIdHelperSvc* sTgcDigitMaker::m_idHelperSvc {nullptr}
private

Definition at line 138 of file sTgcDigitMaker.h.

◆ m_imsg

std::atomic<IMessageSvc*> AthMessaging::m_imsg { nullptr }
mutableprivateinherited

MessageSvc pointer.

Definition at line 135 of file AthMessaging.h.

◆ m_lvl

std::atomic<MSG::Level> AthMessaging::m_lvl { MSG::NIL }
mutableprivateinherited

Current logging level.

Definition at line 138 of file AthMessaging.h.

◆ m_meanGasGain

double sTgcDigitMaker::m_meanGasGain {5.e4}
private

Definition at line 149 of file sTgcDigitMaker.h.

◆ m_mostProbableArrivalTime

std::array<double, 5> sTgcDigitMaker::m_mostProbableArrivalTime {make_array<double, 5>(0.)}
private

Definition at line 133 of file sTgcDigitMaker.h.

◆ m_msg_tls

boost::thread_specific_ptr<MsgStream> AthMessaging::m_msg_tls
mutableprivateinherited

MsgStream instance (a std::cout like with print-out levels)

Definition at line 132 of file AthMessaging.h.

◆ m_nm

std::string AthMessaging::m_nm
privateinherited

Message source name.

Definition at line 129 of file AthMessaging.h.

◆ m_posResAngular

double sTgcDigitMaker::m_posResAngular {0.305/m_StripResolution}
private

Definition at line 158 of file sTgcDigitMaker.h.

◆ m_posResIncident

double sTgcDigitMaker::m_posResIncident {1.}
private

Definition at line 157 of file sTgcDigitMaker.h.

◆ m_stripChargeScale

double sTgcDigitMaker::m_stripChargeScale {0.4}
private

Definition at line 165 of file sTgcDigitMaker.h.

◆ m_StripResolution

double sTgcDigitMaker::m_StripResolution {0.0949}
private

Definition at line 156 of file sTgcDigitMaker.h.

◆ m_theta

double sTgcDigitMaker::m_theta {0.8}
private

Definition at line 148 of file sTgcDigitMaker.h.

◆ m_timeOffsetStrip

std::array<double, 6> sTgcDigitMaker::m_timeOffsetStrip {make_array<double, 6>(0.)}
private

Definition at line 136 of file sTgcDigitMaker.h.


The documentation for this class was generated from the following files:
AthMessaging::m_lvl
std::atomic< MSG::Level > m_lvl
Current logging level.
Definition: AthMessaging.h:138
PlotCalibFromCool.norm
norm
Definition: PlotCalibFromCool.py:100
MuonGM::MuonPadDesign::channelNumber
std::pair< int, int > channelNumber(const Amg::Vector2D &pos) const
calculate local channel number, range 1=nstrips like identifiers.
Definition: MuonPadDesign.cxx:39
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Muon::IMuonIdHelperSvc::stgcIdHelper
virtual const sTgcIdHelper & stgcIdHelper() const =0
access to TgcIdHelper
checkFileSG.line
line
Definition: checkFileSG.py:75
sTgcSimIdToOfflineId
Definition: sTgcSimIdToOfflineId.h:12
sTgcDigitMaker::m_posResIncident
double m_posResIncident
Definition: sTgcDigitMaker.h:157
MuonGM::sTgcReadoutElement::numberOfStrips
virtual int numberOfStrips(const Identifier &layerId) const override final
number of strips per layer
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:410
sTGCSimHit::particleLink
const HepMcParticleLink & particleLink() const
Definition: sTGCSimHit.h:96
PathResolver::find_file
static std::string find_file(const std::string &logical_file_name, const std::string &search_path, SearchType search_type=LocalSearch)
Definition: PathResolver.cxx:251
makeComparison.deltaY
int deltaY
Definition: makeComparison.py:44
sTgcDigitMaker::getTimeOffsetStrip
double getTimeOffsetStrip(size_t neighbor_index) const
Get digit time offset of a strip depending on its relative position to the strip at the centre of the...
Definition: sTgcDigitMaker.cxx:849
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
sTgcDigitMaker::readFileOfTimeOffsetStrip
StatusCode readFileOfTimeOffsetStrip()
Read share/sTGC_Digitization_timeOffsetStrip.dat.
Definition: sTgcDigitMaker.cxx:810
index
Definition: index.py:1
hist_file_dump.d
d
Definition: hist_file_dump.py:137
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
CaloCondBlobAlgs_fillNoiseFromASCII.gain
gain
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:110
sTgcDigitMaker::getMostProbableArrivalTime
double getMostProbableArrivalTime(double distance) const
Get the most probable time of arrival.
Definition: sTgcDigitMaker.cxx:799
sTgcDigitMaker::m_chargeAngularFactor
double m_chargeAngularFactor
Definition: sTgcDigitMaker.h:163
InDet::adjacent
bool adjacent(unsigned int strip1, unsigned int strip2)
Definition: SCT_ClusteringTool.cxx:45
MuonGM::sTgcReadoutElement::getDesign
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:281
mc.diff
diff
Definition: mc.SFGenPy8_MuMu_DD.py:14
athena.value
value
Definition: athena.py:122
Muon::IMuonIdHelperSvc::toStringDetEl
virtual std::string toStringDetEl(const Identifier &id) const =0
print all fields up to detector element to string
MuonGM::sTgcReadoutElement::numberOfWires
int numberOfWires(const Identifier &id) const
Get the total number of wires (single wires) of a chamber.
Definition: MuonDetDescr/MuonReadoutGeometry/src/sTgcReadoutElement.cxx:684
sTgcDigitMaker::readFileOfTimeArrival
StatusCode readFileOfTimeArrival()
Read share/sTGC_Digitization_timeArrival.dat.
Definition: sTgcDigitMaker.cxx:744
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
isValid
bool isValid(const T &p)
Definition: AtlasPID.h:214
AthMessaging::m_imsg
std::atomic< IMessageSvc * > m_imsg
MessageSvc pointer.
Definition: AthMessaging.h:135
python.SystemOfUnits.ms
int ms
Definition: SystemOfUnits.py:132
MuonGM::MuonClusterReadoutElement::surface
virtual const Trk::PlaneSurface & surface() const override
access to chamber surface (phi orientation), uses the first gas gap
Definition: MuonClusterReadoutElement.h:123
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
Trk::energyDeposit
@ energyDeposit
Definition: MeasurementType.h:32
MuonGM::sTgcReadoutElement::stripPosition
virtual bool stripPosition(const Identifier &id, Amg::Vector2D &pos) const override final
strip position - should be renamed to channel position If the strip number is outside the range of va...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:323
MuonGM::MuonPadDesign::nPadH
int nPadH
Definition: MuonPadDesign.h:68
python.SystemOfUnits.keV
int keV
Definition: SystemOfUnits.py:156
sTgcDigitMaker::pointClosestApproach
Ionization pointClosestApproach(const MuonGM::sTgcReadoutElement *readoutEle, const Identifier &id, int wireNumber, const Amg::Vector3D &preStepPos, const Amg::Vector3D &postStepPos) const
Determine the points where the distance between two segments is smallest.
Definition: sTgcDigitMaker.cxx:631
sTgcDigitMaker::m_gammaParameter
std::vector< GammaParameter > m_gammaParameter
Definition: sTgcDigitMaker.h:131
physics_parameters.file_name
string file_name
Definition: physics_parameters.py:32
Trk::PlaneSurface::insideBounds
virtual bool insideBounds(const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const override
This method calls the inside() method of the Bounds.
AthMessaging::AthMessaging
AthMessaging()
Default constructor:
efficiency
void efficiency(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
Definition: dependence.cxx:128
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
TrigConf::MSGTC::Level
Level
Definition: Trigger/TrigConfiguration/TrigConfBase/TrigConfBase/MsgStream.h:21
sTgcDigitMaker::m_posResAngular
double m_posResAngular
Definition: sTgcDigitMaker.h:158
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
xAOD::uint16_t
setWord1 uint16_t
Definition: eFexEMRoI_v1.cxx:88
sTgcDigitMaker::m_channelTypes
int m_channelTypes
define offsets and widths of time windows for signals from wiregangs and strips.
Definition: sTgcDigitMaker.h:147
sTgcDigitMaker::getGammaParameter
GammaParameter getGammaParameter(double distance) const
Find the gamma pdf parameters of a given distance.
Definition: sTgcDigitMaker.cxx:784
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
MuonGM::sTgcReadoutElement::surfaceHash
virtual int surfaceHash(const Identifier &id) const override final
returns the hash to be used to look up the surface and transform in the MuonClusterReadoutElement tra...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:259
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
MuonGM::sTgcReadoutElement
An sTgcReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station c...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:28
Muon::IMuonIdHelperSvc::toStringGasGap
virtual std::string toStringGasGap(const Identifier &id) const =0
print all fields up to gas gap to string
athena.file_path
file_path
Definition: athena.py:92
sTGCSimHit::sTGCId
HitID sTGCId() const
Definition: sTGCSimHit.h:51
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
sTgcDigitMaker::addDigit
static void addDigit(sTgcDigitVec &digits, const Identifier &id, const uint16_t bctag, const double digittime, const double charge)
Definition: sTgcDigitMaker.cxx:729
compareGeometries.deltaX
float deltaX
Definition: compareGeometries.py:32
MuonGM::MuonPadDesign::channelWidth
double channelWidth(const Amg::Vector2D &pos, bool measPhi, bool preciseMeas=false) const
calculate local channel width
Definition: MuonPadDesign.h:142
AthMessaging::msg
MsgStream & msg() const
The standard message stream.
Definition: AthMessaging.h:164
MuonGM::sTgcReadoutElement::channelPitch
double channelPitch(const Identifier &id) const
Channel pitch.
Definition: MuonDetDescr/MuonReadoutGeometry/src/sTgcReadoutElement.cxx:582
min
#define min(a, b)
Definition: cfImp.cxx:40
tolerance
Definition: suep_shower.h:17
sTGCSimHit::globalDirection
const Amg::Vector3D & globalDirection() const
Definition: sTGCSimHit.h:46
sTgcDigitMaker::m_doTimeOffsetStrip
bool m_doTimeOffsetStrip
Definition: sTgcDigitMaker.h:154
sTGCSimHit::kineticEnergy
double kineticEnergy() const
Definition: sTGCSimHit.h:48
sTGCSimHit::globalTime
double globalTime() const
Definition: sTGCSimHit.h:41
createCoolChannelIdFile.par
par
Definition: createCoolChannelIdFile.py:29
sTgcDigitMaker::m_doPadSharing
bool m_doPadSharing
Definition: sTgcDigitMaker.h:150
charge
double charge(const T &p)
Definition: AtlasPID.h:494
sTgcIdHelper
Definition: sTgcIdHelper.h:55
sTgcDigitMaker::getPadChargeFraction
static double getPadChargeFraction(double distance)
Definition: sTgcDigitMaker.cxx:854
MuonGM::MuonPadDesign::nPadColumns
int nPadColumns
Definition: MuonPadDesign.h:69
MuonGM::MuonChannelDesign::wireNumber
int wireNumber(const Amg::Vector2D &pos) const
calculate the sTGC wire number. The method can return a value outside the range [1,...
Definition: MuonChannelDesign.h:259
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
sTGCSimHit::particleEncoding
int particleEncoding() const
Definition: sTGCSimHit.h:45
sTgcDigitMaker::m_clusterProfile
static constexpr std::array< double, 4 > m_clusterProfile
Definition: sTgcDigitMaker.h:161
MuonGM::sTgcReadoutElement::stripNumber
virtual int stripNumber(const Amg::Vector2D &pos, const Identifier &id) const override final
strip number corresponding to local position.
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:311
DeMoScan.index
string index
Definition: DeMoScan.py:362
Muon::IMuonIdHelperSvc::toString
virtual std::string toString(const Identifier &id) const =0
print all fields to string
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Trk::PlaneSurface
Definition: PlaneSurface.h:64
sTgcDigitMaker::m_timeOffsetStrip
std::array< double, 6 > m_timeOffsetStrip
Definition: sTgcDigitMaker.h:136
sTgcDigitMaker::m_stripChargeScale
double m_stripChargeScale
Definition: sTgcDigitMaker.h:165
known
Definition: TrigBStoxAODTool.cxx:107
AthMessaging::m_nm
std::string m_nm
Message source name.
Definition: AthMessaging.h:129
sTgcDigitMaker::m_theta
double m_theta
Definition: sTgcDigitMaker.h:148
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
sTgcDigitMaker::m_mostProbableArrivalTime
std::array< double, 5 > m_mostProbableArrivalTime
Definition: sTgcDigitMaker.h:133
sTGCSimHit::depositEnergy
double depositEnergy() const
Definition: sTGCSimHit.h:47
sTgcDigitMaker::m_StripResolution
double m_StripResolution
Definition: sTgcDigitMaker.h:156
sTgcDigitMaker::sTgcDigitVec
std::vector< std::unique_ptr< sTgcDigit > > sTgcDigitVec
Definition: sTgcDigitMaker.h:64
MuonGM::sTgcReadoutElement::getPadDesign
const MuonPadDesign * getPadDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:287
MuonGM::sTgcReadoutElement::wirePitch
double wirePitch(int gas_gap=1) const
single wire pitch.
Definition: MuonDetDescr/MuonReadoutGeometry/src/sTgcReadoutElement.cxx:657
AthMessaging::initMessaging
void initMessaging() const
Initialize our message level and MessageSvc.
Definition: AthMessaging.cxx:39
sTGCSimHit::globalPrePosition
const Amg::Vector3D & globalPrePosition() const
Definition: sTGCSimHit.h:49
sTgcDigitMaker::m_meanGasGain
double m_meanGasGain
Definition: sTgcDigitMaker.h:149
AthMessaging::m_msg_tls
boost::thread_specific_ptr< MsgStream > m_msg_tls
MsgStream instance (a std::cout like with print-out levels)
Definition: AthMessaging.h:132
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
Trk::Surface::transform
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
sTGCSimHit::globalPosition
const Amg::Vector3D & globalPosition() const
Definition: sTGCSimHit.h:44
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:25
sTgcDigitMaker::m_idHelperSvc
const Muon::IMuonIdHelperSvc * m_idHelperSvc
Definition: sTgcDigitMaker.h:138
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37