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())};
427 const float stepX{cX / numberOfSteps};
428 const float stepY{cY / numberOfSteps};
429 const float stepZ{cZ / numberOfSteps};
446 for (
int istep{0}; istep < numberOfSteps; ++istep) {
448 float z1{zhit + stepZ * dstep};
452 float zReadout{
static_cast<float>(0.5 * thickness - design->
readoutSide() * z1)};
453 const double spess{zReadout};
457 h.m_h_depD->Fill(z1);
458 h.m_h_spess->Fill(spess);
461 float t_drift{
driftTime(zReadout, element, ctx)};
462 if (t_drift>-2.0000002 and t_drift<-1.9999998) {
463 ATH_MSG_DEBUG(
"Checking for rounding errors in compression");
464 if ((std::abs(z1) - 0.5 * thickness) < 0.000010) {
465 ATH_MSG_DEBUG(
"Rounding error found attempting to correct it. z1 = " << std::fixed << std::setprecision(8) << z1);
467 z1 = 0.0000005 - 0.5 * thickness;
470 z1 = 0.5 * thickness - 0.0000005;
473 zReadout = 0.5 * thickness - design->
readoutSide() * z1;
474 t_drift =
driftTime(zReadout, element, ctx);
475 if (t_drift>-2.0000002 and t_drift<-1.9999998) {
478 ATH_MSG_DEBUG(
"Correction Successful! z1 = " << std::fixed << std::setprecision(8) << z1 <<
", zReadout = " << zReadout <<
", t_drift = " << t_drift);
481 ATH_MSG_DEBUG(
"No rounding error found. Making no correction.");
485 const float x1{xhit + stepX * dstep};
486 float y1{yhit + stepY * dstep};
491 y1 += tanLorentz * zReadout;
495 const float rx{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
496 const float xd{x1 + sigma * rx};
497 const float ry{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
498 const float yd{y1 + sigma * ry};
501 const double stripPitch{0.080};
502 double dstrip{y1 / stripPitch};
504 dstrip = dstrip - std::trunc(dstrip);
506 dstrip = dstrip - std::trunc(dstrip) + 1;
510 double y0{dstrip * stripPitch};
511 double z0{thickness - zReadout};
517 h.m_h_zhit->Fill(zhit);
519 double trap_pos{-999999.}, drift_time{-999999.};
524 double Q_m2{0.}, Q_m1{0.}, Q_00{0.}, Q_p1{0.}, Q_p2{0.};
526 dstrip = y1 / stripPitch;
532 dstrip -=
static_cast<double>(
static_cast<int>(dstrip));
534 dstrip -=
static_cast<double>(
static_cast<int>(dstrip)) + 1;
538 double yfin{dstrip * stripPitch};
539 double zfin{thickness - trap_pos};
541 m_radDamageTool->holeTransport(y0, z0, yfin, zfin, Q_m2, Q_m1, Q_00, Q_p1, Q_p2);
543 const double ystrip{yd +
strip * stripPitch};
552 const double time{drift_time};
573 const double mm2cm = 0.1;
577 Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
582 Q_m2, Q_m1, Q_00, Q_p1, Q_p2,
587 if (Q_00[it] == 0.0)
continue;
588 double ICM_time{(it+0.5)*0.5 + timeOfFlight};
590 Q_m2[it], Q_m1[it], Q_00[it], Q_p1[it], Q_p2[it]
593 double ystrip{y1 +
strip * stripPitch};
598 ICM_time, hitproc, trklink)));
608 const float totaltime{(
m_tfix > -998.) ?
m_tfix.value() : t_drift + timeOfFlight + t_surf};
611 ATH_MSG_VERBOSE(std::fixed << std::setprecision(8) <<
"Local position (phi, eta, depth): ("
612 << position.
xPhi() <<
", " << position.
xEta() <<
", " << position.
xDepth()
613 <<
") of the element is out of active area, charge = " << q1);
625 double& drift_time)
const {
626 if (element==
nullptr) {
627 ATH_MSG_ERROR(
"StripSurfaceChargesGenerator::chargeIsTrapped element is nullptr");
630 bool isTrapped{
false};
638 h.m_h_efieldz->Fill(spess, electric_field);
639 h.m_h_efield->Fill(electric_field);
640 h.m_h_mob_Char->Fill(electric_field, mobChar);
641 h.m_h_vel->Fill(electric_field, electric_field * mobChar);
646 trap_pos = spess - z_trap;
649 h.m_h_drift_time->Fill(drift_time);
650 h.m_h_t_electrode->Fill(t_electrode);
651 h.m_h_drift_electrode->Fill(drift_time, t_electrode);
652 h.m_h_ztrap_tot->Fill(z_trap);
656 if (drift_time < t_electrode) {
658 ATH_MSG_INFO(
"drift_time: " << drift_time <<
" t_electrode: " << t_electrode <<
" spess " << spess);
662 h.m_h_ztrap->Fill(z_trap);
663 h.m_h_trap_drift_t->Fill(drift_time);
664 h.m_h_drift1->Fill(spess, drift_time / t_electrode);
665 h.m_h_gen->Fill(spess, drift_time);
666 h.m_h_gen1->Fill(spess, z_trap);
667 h.m_h_gen2->Fill(spess, z_trap / drift_time * t_electrode);
668 h.m_h_velocity_trap->Fill(electric_field, z_trap / drift_time);
669 h.m_h_mobility_trap->Fill(electric_field, z_trap / drift_time / electric_field);
670 h.m_h_trap_pos->Fill(trap_pos);
677 h.m_h_no_ztrap->Fill(z_trap);
678 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)
char data[hepevt_bytes_allocation_ATLAS]
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.
bool chargeIsTrapped(double spess, const InDetDD::SiDetectorElement *element, double &trap_pos, double &drift_time) const
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
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: ...
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
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