23#include "CLHEP/Geometry/Point3D.h"
24#include "CLHEP/Random/RandomEngine.h"
25#include "CLHEP/Random/RandGaussZiggurat.h"
27#include "GaudiKernel/ConcurrencyFlags.h"
41 const std::string& name,
42 const IInterface* parent)
43 : base_class(
type, name, parent) {
68 if (Gaudi::Concurrency::ConcurrencyFlags::numThreads() > 1) {
69 ATH_MSG_FATAL(
"Filling histograms not supported in MT jobs.");
70 return StatusCode::FAILURE;
75 m_h = std::make_unique<Hists>();
82 const SCT_ID* sct_id{
nullptr};
83 ATH_CHECK(detStore()->retrieve(sct_id,
"SCT_ID"));
94 ATH_MSG_INFO(
"\tsurface drift still not on, wrong params");
99 ATH_MSG_FATAL(
"\tCannot set both FixedTime and SubtractTime options!");
100 ATH_MSG_INFO(
"\tMake sure the two flags are not set simultaneously in jo");
101 return StatusCode::FAILURE;
106 return StatusCode::SUCCESS;
111 m_h_efieldz =
new TProfile(
"efieldz",
"", 50, 0., 0.4);
114 m_h_efield =
new TH1F(
"efield",
"", 100, 200., 800.);
117 m_h_spess =
new TH1F(
"spess",
"", 50, 0., 0.4);
120 m_h_depD =
new TH1F(
"depD",
"", 50, -0.3, 0.3);
132 m_h_ztrap =
new TH1F(
"ztrap",
"", 100, 0., 0.3);
136 m_h_zhit =
new TH1F(
"zhit",
"", 50, -0.2, 0.2);
151 m_h_mob_Char =
new TProfile(
"mob_Char",
"", 200, 100., 1000.);
154 m_h_vel =
new TProfile(
"vel",
"", 100, 100., 1000.);
157 m_h_drift1 =
new TProfile(
"drift1",
"", 50, 0., 0.3);
160 m_h_gen =
new TProfile(
"gen",
"", 50, 0., 0.3);
163 m_h_gen1 =
new TProfile(
"gen1",
"", 50, 0., 0.3);
166 m_h_gen2 =
new TProfile(
"gen2",
"", 50, 0., 0.3);
178 return StatusCode::SUCCESS;
187 return StatusCode::SUCCESS;
194 if (element==
nullptr) {
195 ATH_MSG_ERROR(
"StripSurfaceChargesGenerator::process element is nullptr");
199 if (design==
nullptr) {
200 ATH_MSG_ERROR(
"StripSurfaceChargesGenerator::process can not get " << design);
203 const double thickness{design->
thickness()};
206 if ((zhit < 0.0) or (zhit > thickness)) {
207 ATH_MSG_DEBUG(
"driftTime: hit coordinate zhit=" << zhit / CLHEP::micrometer <<
" out of range");
211 float depletionVoltage{0.};
212 float biasVoltage{0.};
217 depletionVoltage =
m_vdepl * CLHEP::volt;
218 biasVoltage =
m_vbias * CLHEP::volt;
221 const float denominator{
static_cast<float>(depletionVoltage + biasVoltage - (2.0 * zhit * depletionVoltage / thickness))};
222 if (denominator <= 0.0) {
223 if (biasVoltage >= depletionVoltage) {
225 ATH_MSG_ERROR(
"driftTime: negative argument X for log(X) " << zhit);
234 float t_drift{std::log((depletionVoltage + biasVoltage) / denominator)};
235 t_drift *= thickness * thickness / (2.0 *
m_siPropertiesTool->getSiProperties(hashId, ctx).holeDriftMobility() * depletionVoltage);
243 if (element==
nullptr) {
244 ATH_MSG_ERROR(
"StripSurfaceChargesGenerator::diffusionSigma element is nullptr");
248 const float t{
driftTime(zhit, element, ctx)};
251 const float sigma{
static_cast<float>(std::sqrt(2. *
m_siPropertiesTool->getSiProperties(hashId, ctx).holeDiffusionConstant() * t))};
263 const float sensorThickness{
static_cast<float>(element->
thickness())};
264 return driftTime(sensorThickness, element, ctx);
276 const float sensorThickness{
static_cast<float>(element->
thickness())};
291 float t_surfaceDrift{0.};
299 return t_surfaceDrift;
316 CLHEP::HepRandomEngine * rndmEngine,
317 const EventContext& ctx) {
330 unsigned short p_eventId,
331 CLHEP::HepRandomEngine* rndmEngine,
332 const EventContext& ctx)
const {
335 if (initialDesign==
nullptr) {
336 ATH_MSG_ERROR(
"StripSurfaceChargesGenerator::process can not get " << initialDesign);
346 if(motherDesign!=
nullptr){
348 design = motherDesign;
351 ATH_MSG_DEBUG(
"No Mother Design - Using Design from DetElement directly!");
352 design = initialDesign;
355 const double thickness{design->
thickness()};
363 float timeOfFlight{p_eventTime +
hitTime(phit)};
366 timeOfFlight -= (element->
center().
mag()) / CLHEP::c_light;
376 const float xEta{
static_cast<float>(pos[
SiHit::xEta])};
377 const float xPhi{
static_cast<float>(pos[
SiHit::xPhi])};
378 const float xDep{
static_cast<float>(pos[
SiHit::xDep])};
381 const float cEta{
static_cast<float>(endPos[
SiHit::xEta]) - xEta};
382 const float cPhi{
static_cast<float>(endPos[
SiHit::xPhi]) - xPhi};
383 const float cDep{
static_cast<float>(endPos[
SiHit::xDep]) - xDep};
387 const float largeStep{std::sqrt(cEta*cEta + cPhi*cPhi + cDep*cDep)};
390 const float e1{
static_cast<float>(phit.
energyLoss() / steps)};
391 const float q1{
static_cast<float>(e1 *
m_siPropertiesTool->getSiProperties(hashId, ctx).electronHolePairsPerEnergy())};
431 const float stepX{cX / numberOfSteps};
432 const float stepY{cY / numberOfSteps};
433 const float stepZ{cZ / numberOfSteps};
450 for (
int istep{0}; istep < numberOfSteps; ++istep) {
452 float z1{zhit + stepZ * dstep};
456 float zReadout{
static_cast<float>(0.5 * thickness - design->
readoutSide() * z1)};
457 const double spess{zReadout};
461 h.m_h_depD->Fill(z1);
462 h.m_h_spess->Fill(spess);
465 float t_drift{
driftTime(zReadout, element, ctx)};
466 if (t_drift>-2.0000002 and t_drift<-1.9999998) {
467 ATH_MSG_DEBUG(
"Checking for rounding errors in compression");
468 if ((std::abs(z1) - 0.5 * thickness) < 0.000010) {
469 ATH_MSG_DEBUG(
"Rounding error found attempting to correct it. z1 = " << std::fixed << std::setprecision(8) << z1);
471 z1 = 0.0000005 - 0.5 * thickness;
474 z1 = 0.5 * thickness - 0.0000005;
477 zReadout = 0.5 * thickness - design->
readoutSide() * z1;
478 t_drift =
driftTime(zReadout, element, ctx);
479 if (t_drift>-2.0000002 and t_drift<-1.9999998) {
482 ATH_MSG_DEBUG(
"Correction Successful! z1 = " << std::fixed << std::setprecision(8) << z1 <<
", zReadout = " << zReadout <<
", t_drift = " << t_drift);
485 ATH_MSG_DEBUG(
"No rounding error found. Making no correction.");
489 const float x1{xhit + stepX * dstep};
490 float y1{yhit + stepY * dstep};
495 y1 += tanLorentz * zReadout;
499 const float rx{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
500 const float xd{x1 + sigma * rx};
501 const float ry{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
502 const float yd{y1 + sigma * ry};
505 const double stripPitch{0.080};
506 double dstrip{y1 / stripPitch};
508 dstrip = dstrip - std::trunc(dstrip);
510 dstrip = dstrip - std::trunc(dstrip) + 1;
514 double y0{dstrip * stripPitch};
515 double z0{thickness - zReadout};
521 h.m_h_zhit->Fill(zhit);
523 double trap_pos{-999999.}, drift_time{-999999.};
528 double Q_m2{0.}, Q_m1{0.}, Q_00{0.}, Q_p1{0.}, Q_p2{0.};
530 dstrip = y1 / stripPitch;
536 dstrip -=
static_cast<double>(
static_cast<int>(dstrip));
538 dstrip -=
static_cast<double>(
static_cast<int>(dstrip)) + 1;
542 double yfin{dstrip * stripPitch};
543 double zfin{thickness - trap_pos};
545 m_radDamageTool->holeTransport(y0, z0, yfin, zfin, Q_m2, Q_m1, Q_00, Q_p1, Q_p2, ctx);
547 const double ystrip{yd +
strip * stripPitch};
556 const double time{drift_time};
577 const double mm2cm = 0.1;
581 Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
586 Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
591 if (Q_00[it] == 0.0)
continue;
592 double ICM_time{(it+0.5)*0.5 + timeOfFlight};
594 Q_m2[it], Q_m1[it], Q_00[it], Q_p1[it], Q_p2[it]
597 double ystrip{y1 +
strip * stripPitch};
602 ICM_time, hitproc, trklink)));
612 const float totaltime{(
m_tfix > -998.) ?
m_tfix.value() : t_drift + timeOfFlight + t_surf};
615 ATH_MSG_VERBOSE(std::fixed << std::setprecision(8) <<
"Local position (phi, eta, depth): ("
616 << position.xPhi() <<
", " << position.xEta() <<
", " << position.xDepth()
617 <<
") of the element is out of active area, charge = " << q1);
630 const EventContext& ctx)
const {
631 if (element==
nullptr) {
632 ATH_MSG_ERROR(
"StripSurfaceChargesGenerator::chargeIsTrapped element is nullptr");
635 bool isTrapped{
false};
643 h.m_h_efieldz->Fill(spess, electric_field);
644 h.m_h_efield->Fill(electric_field);
645 h.m_h_mob_Char->Fill(electric_field, mobChar);
646 h.m_h_vel->Fill(electric_field, electric_field * mobChar);
651 trap_pos = spess - z_trap;
654 h.m_h_drift_time->Fill(drift_time);
655 h.m_h_t_electrode->Fill(t_electrode);
656 h.m_h_drift_electrode->Fill(drift_time, t_electrode);
657 h.m_h_ztrap_tot->Fill(z_trap);
661 if (drift_time < t_electrode) {
663 ATH_MSG_INFO(
"drift_time: " << drift_time <<
" t_electrode: " << t_electrode <<
" spess " << spess);
667 h.m_h_ztrap->Fill(z_trap);
668 h.m_h_trap_drift_t->Fill(drift_time);
669 h.m_h_drift1->Fill(spess, drift_time / t_electrode);
670 h.m_h_gen->Fill(spess, drift_time);
671 h.m_h_gen1->Fill(spess, z_trap);
672 h.m_h_gen2->Fill(spess, z_trap / drift_time * t_electrode);
673 h.m_h_velocity_trap->Fill(electric_field, z_trap / drift_time);
674 h.m_h_mobility_trap->Fill(electric_field, z_trap / drift_time / electric_field);
675 h.m_h_trap_pos->Fill(trap_pos);
682 h.m_h_no_ztrap->Fill(z_trap);
683 h.m_h_notrap_drift_t->Fill(drift_time);
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.
#define ATLAS_THREAD_SAFE
Header file for AthHistogramAlgorithm.
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.
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
BooleanProperty m_doTrapping
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
float maxDriftTime(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max drift charge equivalent to the detector thickness
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
float m_tHalfwayDrift
Surface drift time.
ServiceHandle< ITHistSvc > m_thistSvc
BooleanProperty m_isOverlay
BooleanProperty m_useSiCondDB
bool m_SurfaceDriftFlag
surface drift ON/OFF
virtual StatusCode initialize() override
AlgTool initialize.
float surfaceDriftTime(float ysurf) const
Calculate of the surface drift time.
float diffusionSigma(float zhit, const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
calculate diffusion sigma from a gaussian dist scattered charge
IntegerProperty m_numberOfCharges
void processSiHit(const InDetDD::SiDetectorElement *element, const SiHit &phit, ISiSurfaceChargesInserter &inserter, float eventTime, unsigned short eventID, CLHEP::HepRandomEngine *rndmEngine, const EventContext &ctx) const
ToolHandle< ISiPropertiesTool > m_siPropertiesTool
virtual StatusCode finalize() override
AlgTool finalize.
FloatProperty m_tsubtract
FloatProperty m_tSurfaceDrift
related to the surface drift
std::unique_ptr< Hists > m_h
ToolHandle< ISiLorentzAngleTool > m_lorentzAngleTool
bool chargeIsTrapped(double spess, const InDetDD::SiDetectorElement *element, double &trap_pos, double &drift_time, const EventContext &ctx) const
BooleanProperty m_doHistoTrap
ToolHandle< ISiliconConditionsTool > m_siConditionsTool
float m_distInterStrip
Inter strip distance normalized to 1.
BooleanProperty m_doInducedChargeModel
float maxDiffusionSigma(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max sigma diffusion
std::unique_ptr< InducedChargeModel > m_InducedChargeModel
StripSurfaceChargesGenerator(const std::string &type, const std::string &name, const IInterface *parent)
constructor
float m_distHalfInterStrip
Half way distance inter strip.
FloatProperty m_smallStepLength
ToolHandle< ISCT_RadDamageSummaryTool > m_radDamageTool
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 ...
const SCT_ModuleSideDesign * getMother() const
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
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.
TProfile * m_h_velocity_trap
TH2F * m_h_drift_electrode
StatusCode book(ITHistSvc &histSvc)
TH1F * m_h_notrap_drift_t
TProfile * m_h_mobility_trap