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())};
382 const float StepX{cEta / numberOfSteps};
383 const float StepY{cPhi / numberOfSteps};
384 const float StepZ{cDep / numberOfSteps};
401 for (
int istep{0}; istep < numberOfSteps; ++istep) {
403 float z1{zhit + StepZ * dstep};
407 float zReadout{
static_cast<float>(0.5 * thickness - design->
readoutSide() * z1)};
408 const double spess{zReadout};
415 float t_drift{
driftTime(zReadout, element, ctx)};
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);
421 z1 = 0.0000005 - 0.5 * thickness;
424 z1 = 0.5 * thickness - 0.0000005;
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) {
432 ATH_MSG_DEBUG(
"Correction Successful! z1 = " << std::fixed << std::setprecision(8) << z1 <<
", zReadout = " << zReadout <<
", t_drift = " << t_drift);
435 ATH_MSG_DEBUG(
"No rounding error found. Making no correction.");
439 const float x1{xhit + StepX * dstep};
440 float y1{yhit + StepY * dstep};
445 y1 += tanLorentz * zReadout;
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};
455 const double stripPitch{0.080};
456 double dstrip{y1 / stripPitch};
458 dstrip = dstrip - std::trunc(dstrip);
460 dstrip = dstrip - std::trunc(dstrip) + 1;
464 double y0{dstrip * stripPitch};
465 double z0{thickness - zReadout};
472 double trap_pos{-999999.}, drift_time{-999999.};
477 double Q_all[5]={0.0,0.0,0.0,0.0,0.0};
479 dstrip = y1 / stripPitch;
485 dstrip -=
static_cast<double>(
static_cast<int>(dstrip));
487 dstrip -=
static_cast<double>(
static_cast<int>(dstrip)) + 1;
491 double yfin{dstrip * stripPitch};
492 double zfin{thickness - trap_pos};
494 m_radDamageTool->holeTransport(y0, z0, yfin, zfin, Q_all[0], Q_all[1], Q_all[2], Q_all[3], Q_all[4]);
496 const double ystrip{yd +
strip * stripPitch};
500 const double time{drift_time};
521 const double mm2cm = 0.1;
525 Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
530 Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
535 if (Q_00[it] == 0.0)
continue;
536 double ICM_time{(it+0.5)*0.5 + timeOfFlight};
538 Q_m2[it], Q_m1[it], Q_00[it], Q_p1[it], Q_p2[it]
541 double ystrip{y1 +
strip * stripPitch};
546 ICM_time, hitproc, trklink)));
556 const float totaltime{(
m_tfix > -998.) ?
m_tfix.value() : t_drift + timeOfFlight + t_surf};
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);
573 double& drift_time) {
574 if (element==
nullptr) {
575 ATH_MSG_ERROR(
"SCT_SurfaceChargesGenerator::chargeIsTrapped element is nullptr");
578 bool isTrapped{
false};
588 m_h_vel->Fill(electric_field, electric_field * mobChar);
593 trap_pos = spess - z_trap;
602 if (drift_time < t_electrode) {
604 ATH_MSG_INFO(
"drift_time: " << drift_time <<
" t_electrode: " << t_electrode <<
" spess " << spess);
609 m_h_drift1->Fill(spess, drift_time / t_electrode);
610 m_h_gen->Fill(spess, drift_time);
612 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)
char data[hepevt_bytes_allocation_ATLAS]
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: ...
double xDepth() const
position along depth direction:
double xPhi() const
position along phi direction:
double xEta() const
position along eta direction:
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 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.
bool chargeIsTrapped(double spess, const InDetDD::SiDetectorElement *element, double &trap_pos, double &drift_time)
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.