30#include "CLHEP/Units/SystemOfUnits.h"
31#include "CLHEP/Units/PhysicalConstants.h"
34#include "HepPDT/ParticleData.hh"
39#include "CLHEP/Random/RandPoisson.h"
40#include "CLHEP/Random/RandFlat.h"
41#include "CLHEP/Random/RandBinomial.h"
42#include "CLHEP/Random/RandExpZiggurat.h"
43#include "CLHEP/Random/RandGaussZiggurat.h"
56 const HepPDT::ParticleDataTable* pdt,
105 ATH_MSG_FATAL (
"TRT_PAITool for Xenon not defined! no point in continuing!" );
108 ATH_MSG_ERROR (
"TRT_PAITool for Krypton is not defined!!! Xenon TRT_PAITool will be used for Krypton straws!" );
112 ATH_MSG_ERROR (
"TRT_PAITool for Argon is not defined!!! Xenon TRT_PAITool will be used for Argon straws!" );
122 const double intervalBetweenCrossings(
m_settings->timeInterval() / 3.);
130 for (
unsigned int k=0; k<150; k++) {
131 double dist = 10.0*(k+0.5);
142 for (
unsigned int iwheel = 0; iwheel < num->getNEndcapWheels(); ++iwheel)
144 for (
unsigned int iside = 0; iside < 2; ++iside)
146 for (
unsigned int ilayer = 0; ilayer < num->getNEndcapLayers(iwheel); ++ilayer)
156 ATH_MSG_VERBOSE (
"Failed to retrieve endcap element for (iside,iwheel,ilayer)=("
157 << iside<<
", "<<iwheel<<
", "<<ilayer<<
")." );
166 const double zcoordfrac((v.z()>0?v.z():-v.z())/v.mag());
167 if (zcoordfrac<0.98 || zcoordfrac > 1.02)
169 ATH_MSG_WARNING (
"Found endcap straw where the assumption that local x-direction"
170 <<
" is parallel to global z-direction is NOT valid."
171 <<
" Drift times will be somewhat off." );
178 for (
unsigned int phi_it = 0; phi_it < 32; phi_it++)
187 const double coordfrac(atan2(v.x(),v.y()));
188 if (coordfrac>0.2 || coordfrac < -0.2)
190 ATH_MSG_WARNING (
"Found barrel straw where the assumption that local y-direction"
191 <<
" is along the straw is NOT valid."
192 <<
" Drift times will be somewhat off." );
207 double prex,
double prey,
double prez,
208 double postx,
double posty,
double postz,
209 std::vector<cluster>& clusterlist,
int strawGasType,
210 CLHEP::HepRandomEngine* rndmEngine,
211 CLHEP::HepRandomEngine* paiRndmEngine)
217 else if (strawGasType==1) { activePAITool =
m_pPAItoolKr; }
218 else if (strawGasType==2) { activePAITool =
m_pPAItoolAr; }
222 const double deltaX(postx - prex);
223 const double deltaY(posty - prey);
224 const double deltaZ(postz - prez);
225 const double stepLength(sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ));
227 const double meanFreePath(activePAITool->
GetMeanFreePath( scaledKineticEnergy, particleCharge*particleCharge ));
230 const unsigned int numberOfClusters(CLHEP::RandPoisson::shoot(rndmEngine,stepLength / meanFreePath));
234 for (
unsigned int iclus(0); iclus<numberOfClusters; ++iclus)
237 const double lambda(CLHEP::RandFlat::shoot(rndmEngine));
240 double clusE(activePAITool->
GetEnergyTransfer(scaledKineticEnergy, paiRndmEngine));
241 clusterlist.emplace_back(clusE, timeOfHit,
242 prex + lambda * deltaX,
243 prey + lambda * deltaY,
244 prez + lambda * deltaZ);
256 bool & alreadyPrintedPDGcodeWarning,
257 double cosmicEventPhase,
259 bool emulationArflag,
260 bool emulationKrflag,
261 CLHEP::HepRandomEngine* rndmEngine,
262 CLHEP::HepRandomEngine* elecProcRndmEngine,
263 CLHEP::HepRandomEngine* elecNoiseRndmEngine,
264 CLHEP::HepRandomEngine* paiRndmEngine)
270 const int hitID((*i)->GetHitID());
272 const bool isBarrel(region<3 );
276 const bool isECA (region==3);
277 const bool isECB (region==4);
312 double timeOfHit(0.0);
314 const double globalHitTime(
hitTime(*theHit));
315 const double globalTime =
static_cast<double>((*theHit)->GetGlobalTime());
316 const double bunchCrossingTime(globalHitTime - globalTime);
324 const int particleEncoding((*theHit)->GetParticleEncoding());
327 if (particleEncoding == 0)
335 ATH_MSG_WARNING (
"Ignoring sim. particle with pdgcode 0. This warning is only shown once per job" );
344 const double energyDeposit = (*theHit)->GetEnergyDeposit();
350 if ( energyDeposit<30.0 ) {
354 double ArEmulationScaling_BA = 0.05;
355 double ArEmulationScaling_ECA = 0.20;
356 double ArEmulationScaling_ECB = 0.20;
359 double KrEmulationScaling_BA = 0.20;
360 double KrEmulationScaling_ECA = 0.39;
361 double KrEmulationScaling_ECB = 0.39;
364 double trEfficiencyBarrel =
m_settings->trEfficiencyBarrel(strawGasType);
365 double hitx = TRThitGlobalPos[0];
366 double hity = TRThitGlobalPos[1];
367 double hitz = TRThitGlobalPos[2];
368 double hitEta = std::abs(log(tan(0.5*atan2(sqrt(hitx*hitx+hity*hity),hitz))));
369 if ( hitEta < 0.5 ) { trEfficiencyBarrel *= ( 0.833333+0.6666667*hitEta*hitEta ); }
371 if ( strawGasType == 0 && emulationArflag ) { trEfficiencyBarrel *= ArEmulationScaling_BA; }
372 if ( strawGasType == 0 && emulationKrflag ) { trEfficiencyBarrel *= KrEmulationScaling_BA; }
373 if ( CLHEP::RandFlat::shoot(rndmEngine) > trEfficiencyBarrel )
continue;
377 double trEfficiencyEndCapA =
m_settings->trEfficiencyEndCapA(strawGasType);
379 if ( strawGasType == 0 && emulationArflag ) { trEfficiencyEndCapA *= ArEmulationScaling_ECA; }
380 if ( strawGasType == 0 && emulationKrflag ) { trEfficiencyEndCapA *= KrEmulationScaling_ECA; }
381 if ( CLHEP::RandFlat::shoot(rndmEngine) > trEfficiencyEndCapA )
continue;
384 double trEfficiencyEndCapB =
m_settings->trEfficiencyEndCapB(strawGasType);
386 if ( strawGasType == 0 && emulationArflag ) { trEfficiencyEndCapB *= ArEmulationScaling_ECB; }
387 if ( strawGasType == 0 && emulationKrflag ) { trEfficiencyEndCapB *= KrEmulationScaling_ECB; }
388 if ( CLHEP::RandFlat::shoot(rndmEngine) > trEfficiencyEndCapB )
continue;
394 m_clusterlist.emplace_back( energyDeposit*CLHEP::keV, timeOfHit, (*theHit)->GetPostStepX(), (*theHit)->GetPostStepY(), (*theHit)->GetPostStepZ() );
403 m_clusterlist.emplace_back( (*theHit)->GetEnergyDeposit()*CLHEP::keV, timeOfHit, (*theHit)->GetPostStepX(), (*theHit)->GetPostStepY(), (*theHit)->GetPostStepZ() );
407 const HepPDT::ParticleData *particle(
m_pParticleTable->particle(HepPDT::ParticleID(abs(particleEncoding))));
408 double particleCharge(0.);
409 double particleMass(0.);
412 particleCharge = particle->charge();
413 particleMass = particle->mass().value();
422 ATH_MSG_WARNING (
"Data for sim. particle with pdgcode "<<particleEncoding
423 <<
" is not a nucleus and could not be retrieved from PartPropSvc. Assuming mass and charge as pion. Please investigate." );
428 particleCharge =
MC::charge(particleEncoding);
434 particleMass = std::abs( Z*Mp+(
A-Z)*Mn );
436 if (!alreadyPrintedPDGcodeWarning) {
437 ATH_MSG_WARNING (
"Data for sim. particle with pdgcode "<<particleEncoding
438 <<
" could not be retrieved from PartPropSvc (unexpected ion)."
439 <<
" Please Investigate the PDGTABLE.MeV file."
440 <<
" Calculating mass and charge from pdg code."
441 <<
" The result is: Charge = "<<particleCharge<<
" Mass = "<<particleMass<<
"MeV" );
442 alreadyPrintedPDGcodeWarning =
true;
447 if (!particleCharge) {
continue; }
450 ATH_MSG_WARNING (
"Ignoring ionization from particle with pdg code "<<particleEncoding
451 <<
" since it appears to be a massless charged particle. Please investigate." );
459 const double scaledKineticEnergy(
static_cast<double>((*theHit)->GetKineticEnergy()) * ( CLHEP::proton_mass_c2 / particleMass ));
462 (*theHit)->GetPreStepX(),(*theHit)->GetPreStepY(),(*theHit)->GetPreStepZ(),
463 (*theHit)->GetPostStepX(),(*theHit)->GetPostStepY(),(*theHit)->GetPostStepZ(),
509 double lowthreshold, noiseamplitude;
513 lowthreshold = isBarrel ?
m_settings->lowThresholdBar(strawGasType) :
m_settings->lowThresholdEC(strawGasType);
514 noiseamplitude = 0.0;
523 const std::vector<cluster>& clusters,
524 std::vector<TRTElectronicsProcessing::Deposit>& deposits,
526 double cosmicEventPhase,
528 CLHEP::HepRandomEngine* rndmEngine)
538 const bool isBarrel(region<3 );
539 const bool isEC (!isBarrel);
540 const bool isShort (region==1);
541 const bool isLong (region==2);
551 double ionisationPotential =
m_settings->ionisationPotential(strawGasType);
552 double smearingFactor =
m_settings->smearingFactor(strawGasType);
554 std::vector<cluster>::const_iterator currentClusterIter(clusters.begin());
555 const std::vector<cluster>::const_iterator endOfClusterList(clusters.end());
567 double map_x2(0.),map_y2(0.),map_z2(0.);
568 double effectiveField2(0.);
573 globalPosition[0]=TRThitGlobalPos[0]*CLHEP::mm;
574 globalPosition[1]=TRThitGlobalPos[1]*CLHEP::mm;
575 globalPosition[2]=TRThitGlobalPos[2]*CLHEP::mm;
578 fieldCache.
getField (globalPosition.data(), mField.data());
580 map_x2 = mField.x()*mField.x();
581 map_y2 = mField.y()*mField.y();
582 map_z2 = mField.z()*mField.z();
609 for (;currentClusterIter!=endOfClusterList;++currentClusterIter)
612 const double cluster_x(currentClusterIter->xpos);
613 const double cluster_y(currentClusterIter->ypos);
614 const double cluster_z(this->
setClusterZ(currentClusterIter->zpos, isLong, isShort, isEC));
615 const double cluster_x2(cluster_x*cluster_x);
616 const double cluster_y2(cluster_y*cluster_y);
617 double cluster_r2(cluster_x2+cluster_y2);
620 if (cluster_r2<wire_r2) cluster_r2=wire_r2;
621 if (cluster_r2>straw_r2) cluster_r2=straw_r2;
623 const double cluster_r(std::sqrt(cluster_r2));
624 const double cluster_E(currentClusterIter->energy);
625 const unsigned int nprimaryelectrons(
static_cast<unsigned int>( cluster_E / ionisationPotential + 1.0 ) );
630 double depositEnergy(0.);
634 unsigned int nsurvivingprimaryelectrons =
static_cast<unsigned int>(randBinomial->
fire(rndmEngine,nprimaryelectrons) + 0.5);
635 if (nsurvivingprimaryelectrons==0)
continue;
636 const double meanElectronEnergy(ionisationPotential / smearingFactor);
637 for (
unsigned int ielec(0); ielec<nsurvivingprimaryelectrons; ++ielec) {
638 depositEnergy += CLHEP::RandExpZiggurat::shoot(rndmEngine, meanElectronEnergy);
643 const double fluctSigma(sqrt(cluster_E * ionisationPotential * (2 - smearingFactor) / smearingFactor));
645 depositEnergy = CLHEP::RandGaussZiggurat::shoot(rndmEngine, cluster_E, fluctSigma);
646 }
while(depositEnergy<0.0);
661 effectiveField2 = map_z2*cluster_y2/cluster_r2 + map_x2 + map_y2;
670 effectiveField2 = map_z2 + (map_x2+map_y2)*cluster_y2/cluster_r2;
686 double clusterTime(currentClusterIter->time);
691 clusterTime = clusterTime + cosmicEventPhase +
m_settings->jitterTimeOffset()*( CLHEP::RandFlat::shoot(rndmEngine) );
696 double timedirect(0.), timereflect(0.);
700 double expdirect(1.0), expreflect(1.0);
716 const unsigned int kdirect =
static_cast<unsigned int>(std::max(distdirect,0.0)/10);
717 const unsigned int kreflect =
static_cast<unsigned int>(distreflect/10);
723 double commondrifttime =
m_pSimDriftTimeTool->getAverageDriftTime(cluster_r,effectiveField2,strawGasType);
724 double dt = clusterTime + commondrifttime;
725 deposits.emplace_back(0.5*depositEnergy*expdirect, timedirect+dt);
726 deposits.emplace_back(0.5*depositEnergy*expreflect, timereflect+dt);
738 const int mask(0x0000001F);
740 int trtID, ringID, moduleID, layerID, strawID;
741 int wheelID, planeID, sectorID;
746 if ( !(hitID & 0x00200000) ) {
748 strawID = hitID & mask;
749 hitID >>= word_shift;
750 layerID = hitID & mask;
751 hitID >>= word_shift;
752 moduleID = hitID & mask;
753 hitID >>= word_shift;
754 ringID = hitID & mask;
755 trtID = hitID >> word_shift;
760 const Amg::Vector3D v( (*theHit)->GetPreStepX(),(*theHit)->GetPreStepY(),(*theHit)->GetPreStepZ());
766 strawID = hitID & mask;
767 hitID >>= word_shift;
768 planeID = hitID & mask;
769 hitID >>= word_shift;
770 sectorID = hitID & mask;
771 hitID >>= word_shift;
772 wheelID = hitID & mask;
773 trtID = hitID >> word_shift;
776 if (trtID == 3) trtID = 0;
781 if ( endcapElement ) {
782 const Amg::Vector3D v( (*theHit)->GetPreStepX(),(*theHit)->GetPreStepY(),(*theHit)->GetPreStepZ());
788 ATH_MSG_WARNING (
"Could not find global coordinate of a straw - drifttime calculation will be inaccurate" );
789 return {0.0,0.0,0.0};
795 double cluster_z(cluster_z_in);
800 const double longBarrelStrawHalfLength(349.315*CLHEP::mm);
801 const double shortBarrelStrawHalfLength(153.375*CLHEP::mm);
802 const double EndcapStrawHalfLength(177.150*CLHEP::mm);
803 if ( isLong && std::abs(cluster_z)>longBarrelStrawHalfLength+30 ) {
804 double d = cluster_z<0 ? cluster_z+longBarrelStrawHalfLength : cluster_z-longBarrelStrawHalfLength;
805 ATH_MSG_WARNING (
"Long barrel straw cluster is outside the active gas volume z = +- 349.315 mm by " << d <<
" mm.");
809 if ( isShort && std::abs(cluster_z)>shortBarrelStrawHalfLength+30 ) {
810 double d = cluster_z<0 ? cluster_z+shortBarrelStrawHalfLength : cluster_z-shortBarrelStrawHalfLength;
811 ATH_MSG_WARNING (
"Short barrel straw cluster is outside the active gas volume z = +- 153.375 mm by " << d <<
" mm.");
815 if ( isEC && std::abs(cluster_z)>EndcapStrawHalfLength+30 ) {
816 double d = cluster_z<0 ? cluster_z+EndcapStrawHalfLength : cluster_z-EndcapStrawHalfLength;
817 ATH_MSG_WARNING (
"End cap straw cluster is outside the active gas volume z = +- 177.150 mm by " << d <<
" mm.");
float hitTime(const AFP_SIDSimHit &hit)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
ATLAS-specific HepMC functions.
A number of constexpr particle constants to avoid hardcoding them directly in various places.
This is an Identifier helper class for the TRT subdetector.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
Extended TRT_BaseElement to describe a TRT readout element, this is a planar layer with n ( order of ...
const Amg::Transform3D & strawTransform(unsigned int straw) const
Straw transform - fast access in array, in Tracking frame: Amg.
Class to hold different TRT detector elements structures.
const TRT_EndcapElement * getEndcapDetElement(unsigned int positive, unsigned int wheelIndex, unsigned int strawLayerIndex, unsigned int phiIndex) const
const TRT_BarrelElement * getBarrelDetElement(unsigned int positive, unsigned int moduleIndex, unsigned int phiIndex, unsigned int strawLayerIndex) const
The Detector Manager for all TRT Detector elements, it acts as the interface to the detector elements...
Extended class of a TRT_BaseElement to describe a readout elment in the endcap.
Helper class to organize the straw elements on TRT readout elements.
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h).
void getField(const double *ATH_RESTRICT xyz, double *ATH_RESTRICT bxyz, double *ATH_RESTRICT deriv=nullptr)
get B field value at given position xyz[3] is in mm, bxyz[3] is in kT if deriv[9] is given,...
Communication with CondDB.
Class containing parameters and settings used by TRT digitization.
Simulation of noise hits in the TRT.
Amg::Vector3D getGlobalPosition(int hitID, const TimedHitPtr< TRTUncompressedHit > *theHit, const InDetDD::TRT_DetElementContainer *detElements)
std::unique_ptr< CLHEP::RandBinomialFixedP > m_randBinomialXe
const HepPDT::ParticleDataTable * m_pParticleTable
TRTProcessingOfStraw(const TRTDigSettings *, const InDetDD::TRT_DetectorManager *, ITRT_PAITool *, ITRT_SimDriftTimeTool *, TRTElectronicsProcessing *ep, TRTNoise *noise, TRTDigCondBase *digcond, const HepPDT::ParticleDataTable *, const TRT_ID *, ITRT_PAITool *=nullptr, ITRT_PAITool *=nullptr, const ITRT_CalDbTool *=nullptr)
Constructor: Calls Initialize method.
TRTDigCondBase * m_pDigConditions
std::unique_ptr< CLHEP::RandBinomialFixedP > m_randBinomialKr
std::vector< cluster > m_clusterlist
double m_innerRadiusOfStraw
unsigned int m_maxelectrons
std::unique_ptr< CLHEP::RandBinomialFixedP > m_randBinomialAr
void ClustersToDeposits(MagField::AtlasFieldCache &fieldCache, int hitID, const std::vector< cluster > &clusters, std::vector< TRTElectronicsProcessing::Deposit > &deposits, const Amg::Vector3D &TRThitGlobalPos, double m_cosmicEventPhase, int strawGasType, CLHEP::HepRandomEngine *rndmEngine)
Transform the ioniation clusters along the particle trajectory inside a straw to energy deposits (i....
TRTElectronicsProcessing * m_pElectronicsProcessing
void Initialize(const ITRT_CalDbTool *)
Initialize.
std::vector< TRTElectronicsProcessing::Deposit > m_depositList
std::vector< double > m_expattenuation
bool m_timeCorrection
Time to be corrected for flight and wire propagation delays false when beamType='cosmics'.
double m_shiftOfZeroPoint
double m_signalPropagationSpeed
ITRT_PAITool * m_pPAItoolXe
ITRT_PAITool * m_pPAItoolKr
void addClustersFromStep(double scaledKineticEnergy, double particleCharge, double timeOfHit, double prex, double prey, double prez, double postx, double posty, double postz, std::vector< cluster > &clusterlist, int strawGasType, CLHEP::HepRandomEngine *rndmEngine, CLHEP::HepRandomEngine *paiRndmEngine)
This is the main function for re-simulation of the ionisation in the active gas via the PAI model.
TimedHitCollection< TRTUncompressedHit >::const_iterator hitCollConstIter
bool m_useMagneticFieldMap
const TRT_ID * m_id_helper
bool m_alreadywarnedagainstpdg0
ITRT_PAITool * m_pPAItoolAr
double m_attenuationLength
double m_solenoidFieldStrength
void ProcessStraw(MagField::AtlasFieldCache &fieldCache, const InDetDD::TRT_DetElementContainer *detElements, hitCollConstIter i, hitCollConstIter e, TRTDigit &outdigit, bool &m_alreadyPrintedPDGcodeWarning, double m_cosmicEventPhase, int strawGasType, bool emulationArflag, bool emulationKrflag, CLHEP::HepRandomEngine *rndmEngine, CLHEP::HepRandomEngine *elecProcRndmEngine, CLHEP::HepRandomEngine *elecNoiseRndmEngine, CLHEP::HepRandomEngine *paiRndmEngine)
Process this straw all the way from Geant4 hit to output digit.
~TRTProcessingOfStraw()
Destructor.
double m_outerRadiusOfWire
TRTTimeCorrection * m_pTimeCorrection
const TRTDigSettings * m_settings
ITRT_SimDriftTimeTool * m_pSimDriftTimeTool
const InDetDD::TRT_DetectorManager * m_detmgr
double setClusterZ(double cluster_z_in, bool isLong, bool isShort, bool isEC) const
This is an Identifier helper class for the TRT subdetector.
a smart pointer to a hit that also provides access to the extended timing info of the host event.
Eigen::Matrix< double, 3, 1 > Vector3D
int numberOfProtons(const T &p)
bool isGenericMultichargedParticle(const T &p)
In addition, there is a need to identify ”Q-ball” and similar very exotic (multi-charged) particles w...
bool isPhoton(const T &p)
bool isMonopole(const T &p)
PDG rule 11i Magnetic monopoles and dyons are assumed to have one unit of Dirac monopole charge and a...
double charge(const T &p)
bool isNucleus(const T &p)
PDG rule 16 Nuclear codes are given as 10-digit numbers ±10LZZZAAAI.
double baryonNumber(const T &p)
constexpr double protonMassInMeV
the mass of the proton (in MeV)
constexpr double chargedPionMassInMeV
the mass of the charged pion (in MeV)
constexpr double neutronMassInMeV
the mass of the neutron (in MeV)
unsigned int getRegion(int hitID)
hold the test vectors and ease the comparison