23#include "CLHEP/Geometry/Point3D.h"
24#include "CLHEP/Random/RandomEngine.h"
25#include "CLHEP/Random/RandGaussZiggurat.h"
36 const std::string& name,
37 const IInterface* parent)
38 : base_class(
type, name, parent) {
66 m_h_efieldz =
new TProfile(
"efieldz",
"", 50, 0., 0.4);
69 m_h_efield =
new TH1F(
"efield",
"", 100, 200., 800.);
72 m_h_spess =
new TH1F(
"spess",
"", 50, 0., 0.4);
75 m_h_depD =
new TH1F(
"depD",
"", 50, -0.3, 0.3);
87 m_h_ztrap =
new TH1F(
"ztrap",
"", 100, 0., 0.3);
91 m_h_zhit =
new TH1F(
"zhit",
"", 50, -0.2, 0.2);
106 m_h_mob_Char =
new TProfile(
"mob_Char",
"", 200, 100., 1000.);
109 m_h_vel =
new TProfile(
"vel",
"", 100, 100., 1000.);
112 m_h_drift1 =
new TProfile(
"drift1",
"", 50, 0., 0.3);
115 m_h_gen =
new TProfile(
"gen",
"", 50, 0., 0.3);
118 m_h_gen1 =
new TProfile(
"gen1",
"", 50, 0., 0.3);
121 m_h_gen2 =
new TProfile(
"gen2",
"", 50, 0., 0.3);
137 const SCT_ID* sct_id{
nullptr};
138 ATH_CHECK(detStore()->retrieve(sct_id,
"SCT_ID"));
149 ATH_MSG_INFO(
"\tsurface drift still not on, wrong params");
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;
161 return StatusCode::SUCCESS;
169 return StatusCode::SUCCESS;
176 if (element==
nullptr) {
177 ATH_MSG_ERROR(
"SCT_SurfaceChargesGenerator::process element is nullptr");
181 if (design==
nullptr) {
182 ATH_MSG_ERROR(
"SCT_SurfaceChargesGenerator::process can not get " << design);
185 const double thickness{design->
thickness()};
188 if ((zhit < 0.0) or (zhit > thickness)) {
189 ATH_MSG_DEBUG(
"driftTime: hit coordinate zhit=" << zhit / CLHEP::micrometer <<
" out of range");
193 float depletionVoltage{0.};
194 float biasVoltage{0.};
199 depletionVoltage =
m_vdepl * CLHEP::volt;
200 biasVoltage =
m_vbias * CLHEP::volt;
203 const float denominator{
static_cast<float>(depletionVoltage + biasVoltage - (2.0 * zhit * depletionVoltage / thickness))};
204 if (denominator <= 0.0) {
205 if (biasVoltage >= depletionVoltage) {
207 ATH_MSG_ERROR(
"driftTime: negative argument X for log(X) " << zhit);
216 float t_drift{std::log((depletionVoltage + biasVoltage) / denominator)};
217 t_drift *= thickness * thickness / (2.0 *
m_siPropertiesTool->getSiProperties(hashId, ctx).holeDriftMobility() * depletionVoltage);
225 if (element==
nullptr) {
226 ATH_MSG_ERROR(
"SCT_SurfaceChargesGenerator::diffusionSigma element is nullptr");
230 const float t{
driftTime(zhit, element, ctx)};
233 const float sigma{
static_cast<float>(std::sqrt(2. *
m_siPropertiesTool->getSiProperties(hashId, ctx).holeDiffusionConstant() * t))};
245 const float sensorThickness{
static_cast<float>(element->
thickness())};
246 return driftTime(sensorThickness, element, ctx);
258 const float sensorThickness{
static_cast<float>(element->
thickness())};
273 float t_surfaceDrift{0.};
281 return t_surfaceDrift;
298 CLHEP::HepRandomEngine * rndmEngine,
299 const EventContext& ctx) {
312 unsigned short p_eventId,
313 CLHEP::HepRandomEngine* rndmEngine,
314 const EventContext& ctx) {
316 if (design==
nullptr) {
317 ATH_MSG_ERROR(
"SCT_SurfaceChargesGenerator::process can not get " << design);
321 const double thickness{design->
thickness()};
329 float timeOfFlight{p_eventTime +
hitTime(phit)};
332 timeOfFlight -= (element->
center().
mag()) / CLHEP::c_light;
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])};
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};
351 const float LargeStep{std::sqrt(cEta*cEta + cPhi*cPhi + cDep*cDep)};
354 const float e1{
static_cast<float>(phit.
energyLoss() / steps)};
355 const float q1{
static_cast<float>(e1 *
m_siPropertiesTool->getSiProperties(hashId, ctx).electronHolePairsPerEnergy())};
368 ATH_MSG_ERROR(
"SCT_SurfaceChargesGenerator::process has fieldCondObj=nullptr");
386 const float StepX{cEta / numberOfSteps};
387 const float StepY{cPhi / numberOfSteps};
388 const float StepZ{cDep / numberOfSteps};
405 for (
int istep{0}; istep < numberOfSteps; ++istep) {
407 float z1{zhit + StepZ * dstep};
411 float zReadout{
static_cast<float>(0.5 * thickness - design->
readoutSide() * z1)};
412 const double spess{zReadout};
419 float t_drift{
driftTime(zReadout, element, ctx)};
420 if (t_drift>-2.0000002 and t_drift<-1.9999998) {
421 ATH_MSG_DEBUG(
"Checking for rounding errors in compression");
422 if ((std::abs(z1) - 0.5 * thickness) < 0.000010) {
423 ATH_MSG_DEBUG(
"Rounding error found attempting to correct it. z1 = " << std::fixed << std::setprecision(8) << z1);
425 z1 = 0.0000005 - 0.5 * thickness;
428 z1 = 0.5 * thickness - 0.0000005;
431 zReadout = 0.5 * thickness - design->
readoutSide() * z1;
432 t_drift =
driftTime(zReadout, element, ctx);
433 if (t_drift>-2.0000002 and t_drift<-1.9999998) {
436 ATH_MSG_DEBUG(
"Correction Successful! z1 = " << std::fixed << std::setprecision(8) << z1 <<
", zReadout = " << zReadout <<
", t_drift = " << t_drift);
439 ATH_MSG_DEBUG(
"No rounding error found. Making no correction.");
443 const float x1{xhit + StepX * dstep};
444 float y1{yhit + StepY * dstep};
449 y1 += tanLorentz * zReadout;
453 const float rx{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
454 const float xd{x1 + sigma * rx};
455 const float ry{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
456 const float yd{y1 + sigma * ry};
459 const double stripPitch{0.080};
460 double dstrip{y1 / stripPitch};
462 dstrip = dstrip - std::trunc(dstrip);
464 dstrip = dstrip - std::trunc(dstrip) + 1;
468 double y0{dstrip * stripPitch};
469 double z0{thickness - zReadout};
476 double trap_pos{-999999.}, drift_time{-999999.};
481 double Q_all[5]={0.0,0.0,0.0,0.0,0.0};
483 dstrip = y1 / stripPitch;
489 dstrip -=
static_cast<double>(
static_cast<int>(dstrip));
491 dstrip -=
static_cast<double>(
static_cast<int>(dstrip)) + 1;
495 double yfin{dstrip * stripPitch};
496 double zfin{thickness - trap_pos};
498 m_radDamageTool->holeTransport(y0, z0, yfin, zfin, Q_all[0], Q_all[1], Q_all[2], Q_all[3], Q_all[4], ctx);
500 const double ystrip{yd +
strip * stripPitch};
504 const double time{drift_time};
525 const double mm2cm = 0.1;
529 Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
534 Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
539 if (Q_00[it] == 0.0)
continue;
540 double ICM_time{(it+0.5)*0.5 + timeOfFlight};
542 Q_m2[it], Q_m1[it], Q_00[it], Q_p1[it], Q_p2[it]
545 double ystrip{y1 +
strip * stripPitch};
550 ICM_time, hitproc, trklink)));
560 const float totaltime{(
m_tfix > -998.) ?
m_tfix.value() : t_drift + timeOfFlight + t_surf};
563 ATH_MSG_VERBOSE(std::fixed << std::setprecision(8) <<
"Local position (phi, eta, depth): ("
564 << position.xPhi() <<
", " << position.xEta() <<
", " << position.xDepth()
565 <<
") of the element is out of active area, charge = " << q1);
578 const EventContext& ctx) {
579 if (element==
nullptr) {
580 ATH_MSG_ERROR(
"SCT_SurfaceChargesGenerator::chargeIsTrapped element is nullptr");
583 bool isTrapped{
false};
593 m_h_vel->Fill(electric_field, electric_field * mobChar);
598 trap_pos = spess - z_trap;
607 if (drift_time < t_electrode) {
609 ATH_MSG_INFO(
"drift_time: " << drift_time <<
" t_electrode: " << t_electrode <<
" spess " << spess);
614 m_h_drift1->Fill(spess, drift_time / t_electrode);
615 m_h_gen->Fill(spess, drift_time);
617 m_h_gen2->Fill(spess, z_trap / drift_time * t_electrode);
float hitTime(const AFP_SIDSimHit &hit)
Scalar mag() const
mag method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
double charge(const T &p)
This is an Identifier helper class for the SCT subdetector.
a link optimized in size for a GenParticle in a McEventCollection
bool isValid() const
Validity check.
static HepMcParticleLink getRedirectedLink(const HepMcParticleLink &particleLink, uint32_t eventIndex, const EventContext &ctx)
Return a HepMcParticleLink pointing at the same particle, but in a different GenEvent.
This is a "hash" representation of an Identifier.
double thickness() const
Method which returns thickness of the silicon wafer.
int readoutSide() const
ReadoutSide.
Base class for the SCT module side design, extended by the Forward and Barrel module design.
virtual double scaledDistanceToNearestDiode(const SiLocalPosition &chargePos) const =0
give distance to the nearest diode in units of pitch, from 0.0 to 0.5, this method should be fast as ...
virtual bool inActiveArea(const SiLocalPosition &chargePos, bool checkBondGap=true) const =0
check if the position is in active area
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
Amg::Vector2D hitLocalToLocal(double xEta, double xPhi) const
Simulation/Hit local frame to reconstruction local frame.
Data object for SCT_ChargeTrappingTool, SCT_RadDamageSummaryTool, SCT_SurfaceChargesGenerator.
double getTimeToElectrode() const
double getElectricField() const
double getTrappingTime() const
double getTrappingPositionZ() const
double getHoleDriftMobility() const
This is an Identifier helper class for the SCT subdetector.
size_type wafer_hash_max() const
float diffusionSigma(float zhit, const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
calculate diffusion sigma from a gaussian dist scattered charge
ToolHandle< ISCT_RadDamageSummaryTool > m_radDamageTool
float maxDiffusionSigma(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max sigma diffusion
SCT_SurfaceChargesGenerator(const std::string &type, const std::string &name, const IInterface *parent)
constructor
float m_tHalfwayDrift
Surface drift time.
BooleanProperty m_isOverlay
BooleanProperty m_useSiCondDB
TProfile * m_h_mobility_trap
std::unique_ptr< InducedChargeModel > m_InducedChargeModel
BooleanProperty m_doTrapping
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
bool chargeIsTrapped(double spess, const InDetDD::SiDetectorElement *element, double &trap_pos, double &drift_time, const EventContext &ctx)
bool m_SurfaceDriftFlag
surface drift ON/OFF
BooleanProperty m_doHistoTrap
float m_distHalfInterStrip
Half way distance inter strip.
TH1F * m_h_notrap_drift_t
float maxDriftTime(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max drift charge equivalent to the detector thickness
IntegerProperty m_numberOfCharges
ToolHandle< ISiliconConditionsTool > m_siConditionsTool
TH2F * m_h_drift_electrode
void processSiHit(const InDetDD::SiDetectorElement *element, const SiHit &phit, ISiSurfaceChargesInserter &inserter, float eventTime, unsigned short eventID, CLHEP::HepRandomEngine *rndmEngine, const EventContext &ctx)
BooleanProperty m_doInducedChargeModel
ToolHandle< ISiLorentzAngleTool > m_lorentzAngleTool
FloatProperty m_smallStepLength
ServiceHandle< ITHistSvc > m_thistSvc
virtual StatusCode initialize() override
AlgTool initialize.
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
virtual StatusCode finalize() override
AlgTool finalize.
FloatProperty m_tSurfaceDrift
related to the surface drift
FloatProperty m_tsubtract
float m_distInterStrip
Inter strip distance normalized to 1.
TProfile * m_h_velocity_trap
float surfaceDriftTime(float ysurf) const
Calculate of the surface drift time.
ToolHandle< ISiPropertiesTool > m_siPropertiesTool
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
double energyLoss() const
HepGeom::Point3D< double > localStartPosition() const
const HepMcParticleLink & particleLink() const
HepGeom::Point3D< double > localEndPosition() const
a smart pointer to a hit that also provides access to the extended timing info of the host event.
unsigned short eventId() const
the index of the component event in PileUpEventInfo.
float eventTime() const
t0 offset of the bunch xing containing the hit in ns.