ATLAS Offline Software
SCT_SurfaceChargesGenerator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 // DD
10 
11 // Athena
13 #include "InDetIdentifier/SCT_ID.h"
14 #include "InDetSimEvent/SiHit.h" // for SiHit, SiHit::::xDep, etc
15 #include "HitManagement/TimedHitPtr.h" // for TimedHitPtr
16 
17 // ROOT
18 #include "TH1.h" // for TH1F
19 #include "TH2.h" // for TH2F
20 #include "TProfile.h" // for TProfile
21 
22 // CLHEP
23 #include "CLHEP/Geometry/Point3D.h"
24 #include "CLHEP/Random/RandomEngine.h"
25 #include "CLHEP/Random/RandGaussZiggurat.h"
26 
27 // C++ Standard Library
28 #include <cmath>
29 
33 
34 // constructor
36  const std::string& name,
37  const IInterface* parent)
38  : base_class(type, name, parent) {
39 }
40 
41 // ----------------------------------------------------------------------
42 // Initialize
43 // ----------------------------------------------------------------------
45  ATH_MSG_DEBUG("SCT_SurfaceChargesGenerator::initialize()");
46 
47  // Get ISiPropertiesTool
48  ATH_CHECK(m_siPropertiesTool.retrieve());
49 
50  // Get ISiliconConditionsSvc
51  ATH_CHECK(m_siConditionsTool.retrieve());
52 
54 
55  if (m_doTrapping) {
56  // -- Get Radiation Damage Tool
57  ATH_CHECK(m_radDamageTool.retrieve());
58  } else {
59  m_radDamageTool.disable();
60  }
61 
62  if (m_doHistoTrap) {
63  // -- Get Histogram Service
64  ATH_CHECK(m_thistSvc.retrieve());
65 
66  m_h_efieldz = new TProfile("efieldz", "", 50, 0., 0.4);
67  ATH_CHECK(m_thistSvc->regHist("/file1/efieldz", m_h_efieldz));
68 
69  m_h_efield = new TH1F("efield", "", 100, 200., 800.);
70  ATH_CHECK(m_thistSvc->regHist("/file1/efield", m_h_efield));
71 
72  m_h_spess = new TH1F("spess", "", 50, 0., 0.4);
73  ATH_CHECK(m_thistSvc->regHist("/file1/spess", m_h_spess));
74 
75  m_h_depD = new TH1F("depD", "", 50, -0.3, 0.3);
76  ATH_CHECK(m_thistSvc->regHist("/file1/depD", m_h_depD));
77 
78  m_h_drift_electrode = new TH2F("drift_electrode", "", 50, 0., 20., 50, 0., 20.);
79  ATH_CHECK(m_thistSvc->regHist("/file1/drift_electrode", m_h_drift_electrode));
80 
81  m_h_drift_time = new TH1F("drift_time", "", 100, 0., 20.);
82  ATH_CHECK(m_thistSvc->regHist("/file1/drift_time", m_h_drift_time));
83 
84  m_h_t_electrode = new TH1F("t_electrode", "", 100, 0., 20.);
85  ATH_CHECK(m_thistSvc->regHist("/file1/t_electrode", m_h_t_electrode));
86 
87  m_h_ztrap = new TH1F("ztrap", "", 100, 0., 0.3);
88  ATH_CHECK(m_thistSvc->regHist("/file1/ztrap", m_h_ztrap));
89 
90  // More histograms to check what's going on
91  m_h_zhit = new TH1F("zhit", "", 50, -0.2, 0.2);
92  ATH_CHECK(m_thistSvc->regHist("/file1/zhit", m_h_zhit));
93 
94  m_h_ztrap_tot = new TH1F("ztrap_tot", "", 100, 0., 0.5);
95  ATH_CHECK(m_thistSvc->regHist("/file1/ztrap_tot", m_h_ztrap_tot));
96 
97  m_h_no_ztrap = new TH1F("no_ztrap", "", 100, 0., 0.5);
98  ATH_CHECK(m_thistSvc->regHist("/file1/no_ztrap", m_h_no_ztrap));
99 
100  m_h_trap_drift_t = new TH1F("trap_drift_t", "", 100, 0., 20.);
101  ATH_CHECK(m_thistSvc->regHist("/file1/trap_drift_t", m_h_trap_drift_t));
102 
103  m_h_notrap_drift_t = new TH1F("notrap_drift_t", "", 100, 0., 20.);
104  ATH_CHECK(m_thistSvc->regHist("/file1/notrap_drift_t", m_h_notrap_drift_t));
105 
106  m_h_mob_Char = new TProfile("mob_Char", "", 200, 100., 1000.);
107  ATH_CHECK(m_thistSvc->regHist("/file1/mob_Char", m_h_mob_Char));
108 
109  m_h_vel = new TProfile("vel", "", 100, 100., 1000.);
110  ATH_CHECK(m_thistSvc->regHist("/file1/vel", m_h_vel));
111 
112  m_h_drift1 = new TProfile("drift1", "", 50, 0., 0.3);
113  ATH_CHECK(m_thistSvc->regHist("/file1/drift1", m_h_drift1));
114 
115  m_h_gen = new TProfile("gen", "", 50, 0., 0.3);
116  ATH_CHECK(m_thistSvc->regHist("/file1/gen", m_h_gen));
117 
118  m_h_gen1 = new TProfile("gen1", "", 50, 0., 0.3);
119  ATH_CHECK(m_thistSvc->regHist("/file1/gen1", m_h_gen1));
120 
121  m_h_gen2 = new TProfile("gen2", "", 50, 0., 0.3);
122  ATH_CHECK(m_thistSvc->regHist("/file1/gen2", m_h_gen2));
123 
124  m_h_velocity_trap = new TProfile("velocity_trap", "", 50, 0., 1000.);
125  ATH_CHECK(m_thistSvc->regHist("/file1/velocity_trap", m_h_velocity_trap));
126 
127  m_h_mobility_trap = new TProfile("mobility_trap", "", 50, 100., 1000.);
128  ATH_CHECK(m_thistSvc->regHist("/file1/mobility_trap", m_h_mobility_trap));
129 
130  m_h_trap_pos = new TH1F("trap_pos", "", 100, 0., 0.3);
131  ATH_CHECK(m_thistSvc->regHist("/file1/trap_pos", m_h_trap_pos));
132  }
134 
135  // Induced Charge Module.
137  const SCT_ID* sct_id{nullptr};
138  ATH_CHECK(detStore()->retrieve(sct_id, "SCT_ID"));
139  m_InducedChargeModel = std::make_unique<InducedChargeModel>(sct_id->wafer_hash_max());
140  }
141 
142  // Surface drift time calculation Stuff
145  if ((m_tSurfaceDrift > m_tHalfwayDrift) and (m_tHalfwayDrift >= 0.0) and
147  m_SurfaceDriftFlag = true;
148  } else {
149  ATH_MSG_INFO("\tsurface drift still not on, wrong params");
150  }
151 
152  // Make sure these two flags are not set simultaneously
153  if (m_tfix>-998. and m_tsubtract>-998.) {
154  ATH_MSG_FATAL("\tCannot set both FixedTime and SubtractTime options!");
155  ATH_MSG_INFO("\tMake sure the two flags are not set simultaneously in jo");
156  return StatusCode::FAILURE;
157  }
158 
159  ATH_CHECK(m_lorentzAngleTool.retrieve());
160 
161  return StatusCode::SUCCESS;
162 }
163 
164 // ----------------------------------------------------------------------
165 // finalize
166 // ----------------------------------------------------------------------
168  ATH_MSG_DEBUG("SCT_SurfaceChargesGenerator::finalize()");
169  return StatusCode::SUCCESS;
170 }
171 
172 // ----------------------------------------------------------------------
173 // perpandicular Drift time calculation
174 // ----------------------------------------------------------------------
175 float SCT_SurfaceChargesGenerator::driftTime(float zhit, const SiDetectorElement* element, const EventContext& ctx) const {
176  if (element==nullptr) {
177  ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::process element is nullptr");
178  return -2.0;
179  }
180  const SCT_ModuleSideDesign* design{dynamic_cast<const SCT_ModuleSideDesign*>(&(element->design()))};
181  if (design==nullptr) {
182  ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::process can not get " << design);
183  return -2.0;
184  }
185  const double thickness{design->thickness()};
186  const IdentifierHash hashId{element->identifyHash()};
187 
188  if ((zhit < 0.0) or (zhit > thickness)) {
189  ATH_MSG_DEBUG("driftTime: hit coordinate zhit=" << zhit / CLHEP::micrometer << " out of range");
190  return -2.0;
191  }
192 
193  float depletionVoltage{0.};
194  float biasVoltage{0.};
195  if (m_useSiCondDB) {
196  depletionVoltage = m_siConditionsTool->depletionVoltage(hashId, ctx) * CLHEP::volt;
197  biasVoltage = m_siConditionsTool->biasVoltage(hashId, ctx) * CLHEP::volt;
198  } else {
199  depletionVoltage = m_vdepl * CLHEP::volt;
200  biasVoltage = m_vbias * CLHEP::volt;
201  }
202 
203  const float denominator{static_cast<float>(depletionVoltage + biasVoltage - (2.0 * zhit * depletionVoltage / thickness))};
204  if (denominator <= 0.0) {
205  if (biasVoltage >= depletionVoltage) { // Should not happen
206  if(not m_isOverlay) {
207  ATH_MSG_ERROR("driftTime: negative argument X for log(X) " << zhit);
208  }
209  return -1.0;
210  } else {
211  // (m_biasVoltage<m_depletionVoltage) can happen with underdepleted sensors, lose charges in that volume
212  return -10.0;
213  }
214  }
215 
216  float t_drift{std::log((depletionVoltage + biasVoltage) / denominator)};
217  t_drift *= thickness * thickness / (2.0 * m_siPropertiesTool->getSiProperties(hashId, ctx).holeDriftMobility() * depletionVoltage);
218  return t_drift;
219 }
220 
221 // ----------------------------------------------------------------------
222 // Sigma diffusion calculation
223 // ----------------------------------------------------------------------
224 float SCT_SurfaceChargesGenerator::diffusionSigma(float zhit, const SiDetectorElement* element, const EventContext& ctx) const {
225  if (element==nullptr) {
226  ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::diffusionSigma element is nullptr");
227  return 0.0;
228  }
229  const IdentifierHash hashId{element->identifyHash()};
230  const float t{driftTime(zhit, element, ctx)}; // in ns
231 
232  if (t > 0.0) {
233  const float sigma{static_cast<float>(std::sqrt(2. * m_siPropertiesTool->getSiProperties(hashId, ctx).holeDiffusionConstant() * t))}; // in mm
234  return sigma;
235  } else {
236  return 0.0;
237  }
238 }
239 
240 // ----------------------------------------------------------------------
241 // Maximum drift time
242 // ----------------------------------------------------------------------
243 float SCT_SurfaceChargesGenerator::maxDriftTime(const SiDetectorElement* element, const EventContext& ctx) const {
244  if (element) {
245  const float sensorThickness{static_cast<float>(element->thickness())};
246  return driftTime(sensorThickness, element, ctx);
247  } else {
248  ATH_MSG_INFO("Error: SiDetectorElement not set!");
249  return 0.;
250  }
251 }
252 
253 // ----------------------------------------------------------------------
254 // Maximum Sigma difusion
255 // ----------------------------------------------------------------------
256 float SCT_SurfaceChargesGenerator::maxDiffusionSigma(const SiDetectorElement* element, const EventContext& ctx) const {
257  if (element) {
258  const float sensorThickness{static_cast<float>(element->thickness())};
259  return diffusionSigma(sensorThickness, element, ctx);
260  } else {
261  ATH_MSG_INFO("Error: SiDetectorElement not set!");
262  return 0.;
263  }
264 }
265 
266 // ----------------------------------------------------------------------
267 // Calculating the surface drift time but I should confess that
268 // I haven't found out yet where the calculation come from
269 // ----------------------------------------------------------------------
271  if (m_SurfaceDriftFlag) {
272  if ((ysurf >= 0.0) and (ysurf <= m_distInterStrip)) {
273  float t_surfaceDrift{0.};
274  if (ysurf < m_distHalfInterStrip) {
275  const float y{ysurf / m_distHalfInterStrip};
276  t_surfaceDrift= m_tHalfwayDrift * y * y;
277  } else {
278  const float y{(m_distInterStrip - ysurf) / (m_distInterStrip - m_distHalfInterStrip)};
279  t_surfaceDrift = m_tSurfaceDrift + (m_tHalfwayDrift - m_tSurfaceDrift) * y * y;
280  }
281  return t_surfaceDrift;
282  } else {
283  ATH_MSG_INFO(" ysurf out of range " << ysurf);
284  return -1.0;
285  }
286  } else {
287  return 0.0;
288  }
289 }
290 
291 // -------------------------------------------------------------------------------------------
292 // create a list of surface charges from a hit - called from SCT_Digitization
293 // AthAlgorithm
294 // -------------------------------------------------------------------------------------------
296  const TimedHitPtr<SiHit>& phit,
297  ISiSurfaceChargesInserter& inserter,
298  CLHEP::HepRandomEngine * rndmEngine,
299  const EventContext& ctx) {
300  ATH_MSG_VERBOSE("SCT_SurfaceChargesGenerator::process starts");
301  processSiHit(element, *phit, inserter, phit.eventTime(), phit.eventId(), rndmEngine, ctx);
302 }
303 
304 // -------------------------------------------------------------------------------------------
305 // create a list of surface charges from a hit - called from both AthAlgorithm
306 // and PileUpTool
307 // -------------------------------------------------------------------------------------------
309  const SiHit& phit,
310  ISiSurfaceChargesInserter& inserter,
311  float p_eventTime,
312  unsigned short p_eventId,
313  CLHEP::HepRandomEngine* rndmEngine,
314  const EventContext& ctx) {
315  const SCT_ModuleSideDesign* design{dynamic_cast<const SCT_ModuleSideDesign*>(&(element->design()))};
316  if (design==nullptr) {
317  ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::process can not get " << design);
318  return;
319  }
320 
321  const double thickness{design->thickness()};
322  const IdentifierHash hashId{element->identifyHash()};
323  const double tanLorentz{m_lorentzAngleTool->getTanLorentzAngle(hashId)};
324 
325  // ---**************************************
326  // Time of Flight Calculation - separate method?
327  // ---**************************************
328  // --- Original calculation of Time of Flight of the particle Time needed by the particle to reach the sensor
329  float timeOfFlight{p_eventTime + hitTime(phit)};
330 
331  // Kondo 19/09/2007: Use the coordinate of the center of the module to calculate the time of flight
332  timeOfFlight -= (element->center().mag()) / CLHEP::c_light;
333  // !< extract the distance to the origin of the module to Time of flight
334 
335  // !< timing set from jo to adjust (subtract) the timing
336  if (m_tsubtract > -998.) {
337  timeOfFlight -= m_tsubtract;
338  }
339  // ---**************************************
340 
341  const CLHEP::Hep3Vector pos{phit.localStartPosition()};
342  const float xEta{static_cast<float>(pos[SiHit::xEta])};
343  const float xPhi{static_cast<float>(pos[SiHit::xPhi])};
344  const float xDep{static_cast<float>(pos[SiHit::xDep])};
345 
346  const CLHEP::Hep3Vector endPos{phit.localEndPosition()};
347  const float cEta{static_cast<float>(endPos[SiHit::xEta]) - xEta};
348  const float cPhi{static_cast<float>(endPos[SiHit::xPhi]) - xPhi};
349  const float cDep{static_cast<float>(endPos[SiHit::xDep]) - xDep};
350 
351  const float LargeStep{std::sqrt(cEta*cEta + cPhi*cPhi + cDep*cDep)};
352  const int numberOfSteps{static_cast<int>(LargeStep / m_smallStepLength) + 1};
353  const float steps{static_cast<float>(m_numberOfCharges * numberOfSteps)};
354  const float e1{static_cast<float>(phit.energyLoss() / steps)};
355  const float q1{static_cast<float>(e1 * m_siPropertiesTool->getSiProperties(hashId, ctx).electronHolePairsPerEnergy())};
356 
357  // in the following, to test the code, we will use the original coordinate
358  // system of the SCTtest3SurfaceChargesGenerator x is eta y is phi z is depth
359  float xhit{xEta};
360  float yhit{xPhi};
361  float zhit{xDep};
362 
364  if (m_doInducedChargeModel) { // Setting magnetic field for the ICM.
366  const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
367  float vdepl{m_vdepl};
368  float vbias{m_vbias};
369  if (m_useSiCondDB) {
370  vdepl = m_siConditionsTool->depletionVoltage(hashId, ctx);
371  vbias = m_siConditionsTool->biasVoltage(hashId, ctx);
372  }
373  data = m_InducedChargeModel->setWaferData(vdepl,
374  vbias,
375  element,
376  fieldCondObj,
378  rndmEngine,
379  ctx);
380  }
381 
382  const float StepX{cEta / numberOfSteps};
383  const float StepY{cPhi / numberOfSteps};
384  const float StepZ{cDep / numberOfSteps};
385 
386  // check the status of truth information for this SiHit
387  // some Truth information is cut for pile up events
388  const HepMcParticleLink trklink = HepMcParticleLink::getRedirectedLink(phit.particleLink(), p_eventId, ctx); // This link should now correctly resolve to the TruthEvent McEventCollection in the main StoreGateSvc.
390  if (phit.truthID() != 0 || phit.truthBarcode() != 0) { // if the hit was not caused by a delta-ray then one of these must be true
391  if (not trklink.isValid()) {
392  // TODO consider extending this check to reject links to
393  // GenEvents other than the first one in the McEventCollection,
394  // so that the digitization output doesn't change if pile-up
395  // truth is saved.
396  hitproc = SiCharge::cut_track;
397  }
398  }
399 
400  float dstep{-0.5};
401  for (int istep{0}; istep < numberOfSteps; ++istep) {
402  dstep += 1.0;
403  float z1{zhit + StepZ * dstep};
404 
405  // Distance between charge and readout side.
406  // design->readoutSide() is +1 if readout side is in +ve depth axis direction and visa-versa.
407  float zReadout{static_cast<float>(0.5 * thickness - design->readoutSide() * z1)};
408  const double spess{zReadout};
409 
410  if (m_doHistoTrap) {
411  m_h_depD->Fill(z1);
412  m_h_spess->Fill(spess);
413  }
414 
415  float t_drift{driftTime(zReadout, element, ctx)}; // !< t_drift: perpandicular drift time
416  if (t_drift>-2.0000002 and t_drift<-1.9999998) {
417  ATH_MSG_DEBUG("Checking for rounding errors in compression");
418  if ((std::abs(z1) - 0.5 * thickness) < 0.000010) {
419  ATH_MSG_DEBUG("Rounding error found attempting to correct it. z1 = " << std::fixed << std::setprecision(8) << z1);
420  if (z1 < 0.0) {
421  z1 = 0.0000005 - 0.5 * thickness;
422  // set new coordinate to be 0.5nm inside wafer volume.
423  } else {
424  z1 = 0.5 * thickness - 0.0000005;
425  // set new coordinate to be 0.5nm inside wafer volume.
426  }
427  zReadout = 0.5 * thickness - design->readoutSide() * z1;
428  t_drift = driftTime(zReadout, element, ctx);
429  if (t_drift>-2.0000002 and t_drift<-1.9999998) {
430  ATH_MSG_WARNING("Attempt failed. Making no correction.");
431  } else {
432  ATH_MSG_DEBUG("Correction Successful! z1 = " << std::fixed << std::setprecision(8) << z1 << ", zReadout = " << zReadout << ", t_drift = " << t_drift);
433  }
434  } else {
435  ATH_MSG_DEBUG("No rounding error found. Making no correction.");
436  }
437  }
438  if (t_drift > 0.0) {
439  const float x1{xhit + StepX * dstep};
440  float y1{yhit + StepY * dstep};
441 
442  float sigma{0.};
443  if (not m_doInducedChargeModel) {
444  sigma = diffusionSigma(zReadout, element, ctx);
445  y1 += tanLorentz * zReadout; // !< Taking into account the magnetic field
446  } // These are treated in Induced Charge Model.
447 
448  for (int i{0}; i < m_numberOfCharges; ++i) {
449  const float rx{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
450  const float xd{x1 + sigma * rx};
451  const float ry{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
452  const float yd{y1 + sigma * ry};
453 
454  // For charge trapping with Ramo potential
455  const double stripPitch{0.080}; // mm
456  double dstrip{y1 / stripPitch}; // mm
457  if (dstrip > 0.) {
458  dstrip = dstrip - std::trunc(dstrip);
459  } else {
460  dstrip = dstrip - std::trunc(dstrip) + 1;
461  }
462 
463  // now y will be x and z will be y ....just to make sure to confuse everebody
464  double y0{dstrip * stripPitch}; // mm
465  double z0{thickness - zReadout}; // mm
466 
467  // -- Charge Trapping
468  if (m_doTrapping) {
469  if (m_doHistoTrap) {
470  m_h_zhit->Fill(zhit);
471  }
472  double trap_pos{-999999.}, drift_time{-999999.}; // FIXME need better default values
473  if (chargeIsTrapped(spess, element, trap_pos, drift_time)) {
474  if (not m_doRamo) {
475  break;
476  } else { // if we want to take into account also Ramo Potential
477  double Q_all[5]={0.0,0.0,0.0,0.0,0.0};
478 
479  dstrip = y1 / stripPitch; // mm
480  // need the distance from the nearest strips
481  // edge not centre, xtaka = 1/2*stripPitch
482  // centre of detector, y1=0, is in the middle of
483  // an interstrip gap
484  if (dstrip > 0.) {
485  dstrip -= static_cast<double>(static_cast<int>(dstrip));
486  } else {
487  dstrip -= static_cast<double>(static_cast<int>(dstrip)) + 1;
488  }
489 
490  // now y will be x and z will be y ....just to make sure to confuse everebody
491  double yfin{dstrip * stripPitch}; // mm
492  double zfin{thickness - trap_pos}; // mm
493 
494  m_radDamageTool->holeTransport(y0, z0, yfin, zfin, Q_all[0], Q_all[1], Q_all[2], Q_all[3], Q_all[4]);
495  for (int strip{-2}; strip<=2; strip++) {
496  const double ystrip{yd + strip * stripPitch}; // mm
497  const SiLocalPosition position(element->hitLocalToLocal(xd, ystrip));
498  if (design->inActiveArea(position)) {
499  const double charge = Q_all[strip+2];
500  const double time{drift_time};
501  if (charge != 0.) {
502  inserter(SiSurfaceCharge(position, SiCharge(q1*charge, time, hitproc, trklink)));
503  continue;
504  }
505  }
506  }
507  ATH_MSG_INFO("strip zero charge = " << Q_all[2]); // debug
508  } // m_doRamo==true
509  } // chargeIsTrapped()
510  } // m_doTrapping==true
511 
512  if (not m_doRamo) {
513  if (m_doInducedChargeModel) { // Induced Charge Model
514  // Charges storages for 50 ns. 0.5 ns steps.
515  double Q_m2[InducedChargeModel::NTransportSteps]={0};
516  double Q_m1[InducedChargeModel::NTransportSteps]={0};
517  double Q_00[InducedChargeModel::NTransportSteps]={0};
518  double Q_p1[InducedChargeModel::NTransportSteps]={0};
519  double Q_p2[InducedChargeModel::NTransportSteps]={0};
520 
521  const double mm2cm = 0.1; // For mm -> cm conversion
522  // Unit for y and z : mm -> cm in InducedChargeModel
523  m_InducedChargeModel->holeTransport(*data,
524  y0*mm2cm, z0*mm2cm,
525  Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
526  hashId, m_siPropertiesTool,
527  ctx);
528  m_InducedChargeModel->electronTransport(*data,
529  y0*mm2cm, z0*mm2cm,
530  Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
531  hashId, m_siPropertiesTool,
532  ctx);
533 
534  for (int it{0}; it<InducedChargeModel::NTransportSteps; it++) {
535  if (Q_00[it] == 0.0) continue;
536  double ICM_time{(it+0.5)*0.5 + timeOfFlight};
537  double Q_new[InducedChargeModel::NStrips]{
538  Q_m2[it], Q_m1[it], Q_00[it], Q_p1[it], Q_p2[it]
539  };
541  double ystrip{y1 + strip * stripPitch};
542  SiLocalPosition position{element->hitLocalToLocal(x1, ystrip)};
543  if (design->inActiveArea(position)) {
544  inserter(SiSurfaceCharge(position,
546  ICM_time, hitproc, trklink)));
547  }
548  }
549  }
550  } else { // not m_doInducedChargeModel
551  const SiLocalPosition position{element->hitLocalToLocal(xd, yd)};
552  if (design->inActiveArea(position)) {
553  const float sdist{static_cast<float>(design->scaledDistanceToNearestDiode(position))};
554  // !< dist on the surface from the hit point to the nearest strip (diode)
555  const float t_surf{surfaceDriftTime(2.0 * sdist)}; // !< Surface drift time
556  const float totaltime{(m_tfix > -998.) ? m_tfix.value() : t_drift + timeOfFlight + t_surf}; // !< Total drift time
557  inserter(SiSurfaceCharge(position, SiCharge(q1, totaltime, hitproc, trklink)));
558  } else {
559  ATH_MSG_VERBOSE(std::fixed << std::setprecision(8) << "Local position (phi, eta, depth): ("
560  << position.xPhi() << ", " << position.xEta() << ", " << position.xDepth()
561  << ") of the element is out of active area, charge = " << q1);
562  }
563  }
564  }
565  } // end of loop on charges
566  }
567  }
568  }
569 
571  const SiDetectorElement* element,
572  double& trap_pos,
573  double& drift_time) {
574  if (element==nullptr) {
575  ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::chargeIsTrapped element is nullptr");
576  return false;
577  }
578  bool isTrapped{false};
579  const IdentifierHash hashId{element->identifyHash()};
580  const SCT_ChargeTrappingCondData condData{m_radDamageTool->getCondData(hashId, spess)};
581  const double electric_field{condData.getElectricField()};
582 
583  if (m_doHistoTrap) {
584  const double mobChar{condData.getHoleDriftMobility()};
585  m_h_efieldz->Fill(spess, electric_field);
586  m_h_efield->Fill(electric_field);
587  m_h_mob_Char->Fill(electric_field, mobChar);
588  m_h_vel->Fill(electric_field, electric_field * mobChar);
589  }
590  const double t_electrode{condData.getTimeToElectrode()};
591  drift_time = condData.getTrappingTime();
592  const double z_trap{condData.getTrappingPositionZ()};
593  trap_pos = spess - z_trap;
594  if (m_doHistoTrap) {
595  m_h_drift_time->Fill(drift_time);
596  m_h_t_electrode->Fill(t_electrode);
597  m_h_drift_electrode->Fill(drift_time, t_electrode);
598  m_h_ztrap_tot->Fill(z_trap);
599  }
600  // -- Calculate if the charge is trapped, and at which distance
601  // -- Charge gets trapped before arriving to the electrode
602  if (drift_time < t_electrode) {
603  isTrapped = true;
604  ATH_MSG_INFO("drift_time: " << drift_time << " t_electrode: " << t_electrode << " spess " << spess);
605  ATH_MSG_INFO("z_trap: " << z_trap);
606  if (m_doHistoTrap) {
607  m_h_ztrap->Fill(z_trap);
608  m_h_trap_drift_t->Fill(drift_time);
609  m_h_drift1->Fill(spess, drift_time / t_electrode);
610  m_h_gen->Fill(spess, drift_time);
611  m_h_gen1->Fill(spess, z_trap);
612  m_h_gen2->Fill(spess, z_trap / drift_time * t_electrode);
613  m_h_velocity_trap->Fill(electric_field, z_trap / drift_time);
614  m_h_mobility_trap->Fill(electric_field, z_trap / drift_time / electric_field);
615  m_h_trap_pos->Fill(trap_pos);
616  }
617  } else {
618  isTrapped = false;
619  if (m_doHistoTrap) {
620  const double z_trap{condData.getTrappingPositionZ()};
621  m_h_no_ztrap->Fill(z_trap);
622  m_h_notrap_drift_t->Fill(drift_time);
623  }
624  }
625  return isTrapped;
626 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
SiHit::xPhi
@ xPhi
Definition: SiHit.h:162
drawFromPickle.mm2cm
mm2cm
Definition: drawFromPickle.py:31
InducedChargeModel::EndStrip
@ EndStrip
Definition: InducedChargeModel.h:49
InducedChargeModel::NTransportSteps
@ NTransportSteps
Definition: InducedChargeModel.h:47
SCT_SurfaceChargesGenerator::m_tSurfaceDrift
FloatProperty m_tSurfaceDrift
related to the surface drift
Definition: SCT_SurfaceChargesGenerator.h:116
SCT_SurfaceChargesGenerator::m_numberOfCharges
IntegerProperty m_numberOfCharges
Definition: SCT_SurfaceChargesGenerator.h:112
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
SCT_ChargeTrappingCondData
Data object for SCT_ChargeTrappingTool, SCT_RadDamageSummaryTool, SCT_SurfaceChargesGenerator.
Definition: SCT_ChargeTrappingCondData.h:22
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
SCT_ID.h
This is an Identifier helper class for the SCT subdetector. This class is a factory for creating comp...
SCT_SurfaceChargesGenerator::m_h_vel
TProfile * m_h_vel
Definition: SCT_SurfaceChargesGenerator.h:162
SiSurfaceCharge
Definition: SiSurfaceCharge.h:23
pdg_comparison.sigma
sigma
Definition: pdg_comparison.py:324
SCT_SurfaceChargesGenerator::m_lorentzAngleTool
ToolHandle< ISiLorentzAngleTool > m_lorentzAngleTool
Definition: SCT_SurfaceChargesGenerator.h:134
SCT_SurfaceChargesGenerator::m_h_gen1
TProfile * m_h_gen1
Definition: SCT_SurfaceChargesGenerator.h:165
SiliconTech::strip
@ strip
SiHit::localEndPosition
HepGeom::Point3D< double > localEndPosition() const
Definition: SiHit.cxx:153
InducedChargeModel::SCT_InducedChargeModelData
Definition: InducedChargeModel.h:51
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
SCT_SurfaceChargesGenerator::m_doTrapping
BooleanProperty m_doTrapping
Definition: SCT_SurfaceChargesGenerator.h:124
SCT_SurfaceChargesGenerator::finalize
virtual StatusCode finalize() override
AlgTool finalize.
Definition: SCT_SurfaceChargesGenerator.cxx:167
SCT_SurfaceChargesGenerator::m_vbias
FloatProperty m_vbias
Definition: SCT_SurfaceChargesGenerator.h:123
AtlasFieldCacheCondObj
Definition: AtlasFieldCacheCondObj.h:19
egammaEnergyPositionAllSamples::e1
double e1(const xAOD::CaloCluster &cluster)
return the uncorrected cluster energy in 1st sampling
SiHit.h
SCT_SurfaceChargesGenerator::m_h_mob_Char
TProfile * m_h_mob_Char
Definition: SCT_SurfaceChargesGenerator.h:161
SCT_SurfaceChargesGenerator::m_h_gen
TProfile * m_h_gen
Definition: SCT_SurfaceChargesGenerator.h:164
SCT_ModuleSideDesign.h
InDetDD::SCT_ModuleSideDesign
Definition: SCT_ModuleSideDesign.h:40
SCT_SurfaceChargesGenerator::maxDriftTime
float maxDriftTime(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max drift charge equivalent to the detector thickness
Definition: SCT_SurfaceChargesGenerator.cxx:243
InDetDD::SolidStateDetectorElementBase::center
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
SCT_SurfaceChargesGenerator::m_distHalfInterStrip
float m_distHalfInterStrip
Half way distance inter strip.
Definition: SCT_SurfaceChargesGenerator.h:143
SCT_SurfaceChargesGenerator::m_h_efield
TH1F * m_h_efield
Definition: SCT_SurfaceChargesGenerator.h:149
SiCharge::track
@ track
Definition: SiCharge.h:28
SCT_SurfaceChargesGenerator::m_h_no_ztrap
TH1F * m_h_no_ztrap
Definition: SCT_SurfaceChargesGenerator.h:158
SCT_SurfaceChargesGenerator::m_h_spess
TH1F * m_h_spess
Definition: SCT_SurfaceChargesGenerator.h:150
SCT_SurfaceChargesGenerator::m_h_t_electrode
TH1F * m_h_t_electrode
Definition: SCT_SurfaceChargesGenerator.h:155
SCT_SurfaceChargesGenerator::m_InducedChargeModel
std::unique_ptr< InducedChargeModel > m_InducedChargeModel
Definition: SCT_SurfaceChargesGenerator.h:172
skel.it
it
Definition: skel.GENtoEVGEN.py:423
SiCharge
Definition: SiCharge.h:25
SCT_SurfaceChargesGenerator::m_h_zhit
TH1F * m_h_zhit
Definition: SCT_SurfaceChargesGenerator.h:156
SCT_SurfaceChargesGenerator::m_thistSvc
ServiceHandle< ITHistSvc > m_thistSvc
Definition: SCT_SurfaceChargesGenerator.h:136
TimedHitPtr< SiHit >
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SCT_SurfaceChargesGenerator::m_tfix
FloatProperty m_tfix
Definition: SCT_SurfaceChargesGenerator.h:118
python.TrigEgammaMonitorHelper.TH2F
def TH2F(name, title, nxbins, bins_par2, bins_par3, bins_par4, bins_par5=None, bins_par6=None, path='', **kwargs)
Definition: TrigEgammaMonitorHelper.py:45
SCT_SurfaceChargesGenerator::process
virtual void process(const InDetDD::SiDetectorElement *element, const TimedHitPtr< SiHit > &phit, ISiSurfaceChargesInserter &inserter, CLHEP::HepRandomEngine *rndmEngine, const EventContext &ctx) override
create a list of surface charges from a hit
Definition: SCT_SurfaceChargesGenerator.cxx:295
SCT_SurfaceChargesGenerator::m_h_drift1
TProfile * m_h_drift1
Definition: SCT_SurfaceChargesGenerator.h:163
SCT_SurfaceChargesGenerator::m_doRamo
BooleanProperty m_doRamo
Definition: SCT_SurfaceChargesGenerator.h:126
SCT_SurfaceChargesGenerator::m_distInterStrip
float m_distInterStrip
Inter strip distance normalized to 1.
Definition: SCT_SurfaceChargesGenerator.h:142
InDetDD::SolidStateDetectorElementBase::identifyHash
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
makeTRTBarrelCans.y1
tuple y1
Definition: makeTRTBarrelCans.py:15
SiHit
Definition: SiHit.h:19
SCT_SurfaceChargesGenerator::m_tsubtract
FloatProperty m_tsubtract
Definition: SCT_SurfaceChargesGenerator.h:119
TimedHitPtr::eventTime
float eventTime() const
t0 offset of the bunch xing containing the hit in ns.
Definition: TimedHitPtr.h:50
InDetDD::SiLocalPosition
Definition: SiLocalPosition.h:31
InducedChargeModel::StartStrip
@ StartStrip
Definition: InducedChargeModel.h:49
TimedHitPtr.h
SCT_SurfaceChargesGenerator::m_isOverlay
BooleanProperty m_isOverlay
Definition: SCT_SurfaceChargesGenerator.h:127
InducedChargeModel::Offset
@ Offset
Definition: InducedChargeModel.h:49
SCT_SurfaceChargesGenerator.h
SCT_SurfaceChargesGenerator::m_h_ztrap
TH1F * m_h_ztrap
Definition: SCT_SurfaceChargesGenerator.h:153
beamspotman.steps
int steps
Definition: beamspotman.py:505
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:92
InDetDD::SolidStateDetectorElementBase::thickness
double thickness() const
python.TrigEgammaMonitorHelper.TProfile
def TProfile(*args, **kwargs)
Definition: TrigEgammaMonitorHelper.py:81
SCT_SurfaceChargesGenerator::m_h_ztrap_tot
TH1F * m_h_ztrap_tot
Definition: SCT_SurfaceChargesGenerator.h:157
SCT_SurfaceChargesGenerator::m_radDamageTool
ToolHandle< ISCT_RadDamageSummaryTool > m_radDamageTool
Definition: SCT_SurfaceChargesGenerator.h:132
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
SCT_SurfaceChargesGenerator::m_useSiCondDB
BooleanProperty m_useSiCondDB
Definition: SCT_SurfaceChargesGenerator.h:121
SCT_SurfaceChargesGenerator::m_h_gen2
TProfile * m_h_gen2
Definition: SCT_SurfaceChargesGenerator.h:166
SiHit::truthBarcode
int truthBarcode() const
Definition: SiHit.cxx:202
SiHit::particleLink
const HepMcParticleLink & particleLink() const
Definition: SiHit.h:190
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SCT_SurfaceChargesGenerator::m_h_velocity_trap
TProfile * m_h_velocity_trap
Definition: SCT_SurfaceChargesGenerator.h:167
python.SystemOfUnits.micrometer
int micrometer
Definition: SystemOfUnits.py:71
SCT_SurfaceChargesGenerator::m_SurfaceDriftFlag
bool m_SurfaceDriftFlag
surface drift ON/OFF
Definition: SCT_SurfaceChargesGenerator.h:145
TRT::Track::z0
@ z0
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:63
SCT_SurfaceChargesGenerator::m_smallStepLength
FloatProperty m_smallStepLength
Definition: SCT_SurfaceChargesGenerator.h:113
python.SystemOfUnits.volt
int volt
Definition: SystemOfUnits.py:204
ReadTripsProbsFromCool.denominator
denominator
Definition: ReadTripsProbsFromCool.py:96
plotBeamSpotCompare.xd
xd
Definition: plotBeamSpotCompare.py:220
SCT_SurfaceChargesGenerator::m_tHalfwayDrift
float m_tHalfwayDrift
Surface drift time.
Definition: SCT_SurfaceChargesGenerator.h:141
SCT_SurfaceChargesGenerator::m_h_trap_drift_t
TH1F * m_h_trap_drift_t
Definition: SCT_SurfaceChargesGenerator.h:159
InDetDD::SolidStateDetectorElementBase::hitLocalToLocal
Amg::Vector2D hitLocalToLocal(double xEta, double xPhi) const
Simulation/Hit local frame to reconstruction local frame.
Definition: SolidStateDetectorElementBase.cxx:95
SCT_SurfaceChargesGenerator::m_siPropertiesTool
ToolHandle< ISiPropertiesTool > m_siPropertiesTool
Definition: SCT_SurfaceChargesGenerator.h:131
SCT_SurfaceChargesGenerator::driftTime
float driftTime(float zhit, const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
calculate drift time perpandicular to the surface for a charge at distance zhit from mid gap
Definition: SCT_SurfaceChargesGenerator.cxx:175
SCT_SurfaceChargesGenerator::m_h_trap_pos
TH1F * m_h_trap_pos
Definition: SCT_SurfaceChargesGenerator.h:169
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
SCT_SurfaceChargesGenerator::m_h_drift_electrode
TH2F * m_h_drift_electrode
Definition: SCT_SurfaceChargesGenerator.h:152
SCT_SurfaceChargesGenerator::surfaceDriftTime
float surfaceDriftTime(float ysurf) const
Calculate of the surface drift time.
Definition: SCT_SurfaceChargesGenerator.cxx:270
SiHit::energyLoss
double energyLoss() const
Definition: SiHit.h:175
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
SCT_SurfaceChargesGenerator::m_doHistoTrap
BooleanProperty m_doHistoTrap
Definition: SCT_SurfaceChargesGenerator.h:125
SCT_SurfaceChargesGenerator::initialize
virtual StatusCode initialize() override
AlgTool initialize.
Definition: SCT_SurfaceChargesGenerator.cxx:44
charge
double charge(const T &p)
Definition: AtlasPID.h:494
SiHit::xDep
@ xDep
Definition: SiHit.h:162
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
SiHit::truthID
int truthID() const
Definition: SiHit.cxx:208
SiCharge::Process
Process
Definition: SiCharge.h:28
python.PhysicalConstants.c_light
float c_light
Definition: PhysicalConstants.py:63
SiHit::xEta
@ xEta
Definition: SiHit.h:162
SCT_SurfaceChargesGenerator::m_h_mobility_trap
TProfile * m_h_mobility_trap
Definition: SCT_SurfaceChargesGenerator.h:168
InducedChargeModel::NStrips
@ NStrips
Definition: InducedChargeModel.h:49
SiDetectorElement.h
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
SCT_SurfaceChargesGenerator::m_h_notrap_drift_t
TH1F * m_h_notrap_drift_t
Definition: SCT_SurfaceChargesGenerator.h:160
SiCharge::cut_track
@ cut_track
Definition: SiCharge.h:28
y
#define y
TProfile::Fill
int Fill(double, double)
Definition: rootspy.cxx:523
CaloSwCorrections.time
def time(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:242
SCT_ID
Definition: SCT_ID.h:68
TimedHitPtr::eventId
unsigned short eventId() const
the index of the component event in PileUpEventInfo.
Definition: TimedHitPtr.h:42
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
SCT_SurfaceChargesGenerator::m_fieldCacheCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
Definition: SCT_SurfaceChargesGenerator.h:138
SCT_SurfaceChargesGenerator::processSiHit
void processSiHit(const InDetDD::SiDetectorElement *element, const SiHit &phit, ISiSurfaceChargesInserter &inserter, float eventTime, unsigned short eventID, CLHEP::HepRandomEngine *rndmEngine, const EventContext &ctx)
Definition: SCT_SurfaceChargesGenerator.cxx:308
SCT_SurfaceChargesGenerator::SCT_SurfaceChargesGenerator
SCT_SurfaceChargesGenerator(const std::string &type, const std::string &name, const IInterface *parent)
constructor
Definition: SCT_SurfaceChargesGenerator.cxx:35
python.TrigEgammaMonitorHelper.TH1F
def TH1F(name, title, nxbins, bins_par2, bins_par3=None, path='', **kwargs)
Definition: TrigEgammaMonitorHelper.py:24
SCT_SurfaceChargesGenerator::m_doInducedChargeModel
BooleanProperty m_doInducedChargeModel
Definition: SCT_SurfaceChargesGenerator.h:128
hitTime
float hitTime(const AFP_SIDSimHit &hit)
Definition: AFP_SIDSimHit.h:39
IdentifierHash
Definition: IdentifierHash.h:38
SCT_SurfaceChargesGenerator::maxDiffusionSigma
float maxDiffusionSigma(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max sigma diffusion
Definition: SCT_SurfaceChargesGenerator.cxx:256
SCT_SurfaceChargesGenerator::m_vdepl
FloatProperty m_vdepl
Definition: SCT_SurfaceChargesGenerator.h:122
InDetDD::SiDetectorElement::design
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
ISiSurfaceChargesInserter
Definition: ISurfaceChargesGenerator.h:32
SCT_SurfaceChargesGenerator::m_h_drift_time
TH1F * m_h_drift_time
Definition: SCT_SurfaceChargesGenerator.h:154
SCT_SurfaceChargesGenerator::m_siConditionsTool
ToolHandle< ISiliconConditionsTool > m_siConditionsTool
Definition: SCT_SurfaceChargesGenerator.h:133
SCT_SurfaceChargesGenerator::chargeIsTrapped
bool chargeIsTrapped(double spess, const InDetDD::SiDetectorElement *element, double &trap_pos, double &drift_time)
Definition: SCT_SurfaceChargesGenerator.cxx:570
SiHit::localStartPosition
HepGeom::Point3D< double > localStartPosition() const
Definition: SiHit.cxx:146
SCT_SurfaceChargesGenerator::m_h_depD
TH1F * m_h_depD
Definition: SCT_SurfaceChargesGenerator.h:151
SCT_SurfaceChargesGenerator::diffusionSigma
float diffusionSigma(float zhit, const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
calculate diffusion sigma from a gaussian dist scattered charge
Definition: SCT_SurfaceChargesGenerator.cxx:224
SCT_SurfaceChargesGenerator::m_h_efieldz
TProfile * m_h_efieldz
Definition: SCT_SurfaceChargesGenerator.h:148