9#include "GaudiKernel/IRndmGenSvc.h"
10#include "GaudiKernel/RndmGenerators.h"
22#include "CLHEP/Units/SystemOfUnits.h"
23#include "CLHEP/Matrix/Vector.h"
24#include "CLHEP/Random/RandFlat.h"
25#include "CLHEP/Random/RandGauss.h"
26#include "CLHEP/Geometry/Transform3D.h"
29#include "GaudiKernel/ITHistSvc.h"
81 declareProperty(
"ShortenHadIntChain" ,
m_cutChain);
86 declareProperty(
"RandomNumberService" ,
m_rndGenSvc ,
"Random number generator");
87 declareProperty(
"RandomStreamName" ,
m_randomEngineName ,
"Name of the random number stream");
89 declareProperty(
"PhysicsProcessCode" ,
m_processCode ,
"MCTruth Physics Process Code" );
91 declareProperty(
"ParticleBroker" ,
m_particleBroker ,
"ISF ParticleBroker Svc" );
92 declareProperty(
"TruthRecordSvc" ,
m_truthRecordSvc ,
"ISF Particle Truth Svc" );
109 return StatusCode::FAILURE;
117 return StatusCode::FAILURE;
123 return StatusCode::FAILURE;
127 return StatusCode::FAILURE;
135 SmartIF<ITHistSvc> tHistSvc{Gaudi::svcLocator()->service(
"THistSvc")};
137 ATH_MSG_ERROR(
"initialize() Could not find Hist Service -> Switching ValidationMode Off !" );
139 ATH_MSG_VERBOSE(
"Booking hadronic interaction validation TTree ... " );
170 ATH_MSG_ERROR(
"initialize() Could not register the validation Tree -> Switching ValidationMode Off !" );
173 ATH_MSG_INFO(
"TTree for Hadronic Interactions validation booked." );
177 return StatusCode::SUCCESS;
184 return StatusCode::SUCCESS;
189 double p,
double ,
double charge,
201 if (
al>0.) prob = exp( (-1.)*pathCorrection*extMprop->
thickness()/
al );
202 else prob = exp( (-1.)*pathCorrection*extMprop->
thicknessInL0());
205 ATH_MSG_VERBOSE(
" [ had ] Nuclear Interaction length not available, using appox. from X0" );
210 if (msgLvl(MSG::VERBOSE))
230 double al = mat->l0();
241 al *= 1./(1.+ exp(-0.5*(p-270.)*(p-270.)/60./60.));
260 double E = sqrt(p*p + m*m);
263 double multiplicity_max = 0.25 * E/1000. + 18.;
266 double randx , randy, arg = 0.;
282 arg = exp(-0.5*( (randx-p1)/p2 + exp(-(randx-p1)/p2) ) );
283 if (randy < arg && randx>3 && randx<multiplicity_max)
break;
286 randx *= (1.2-0.4*exp(-0.001*p));
288 int Npart = (int)randx;
292 ATH_MSG_VERBOSE(
"[ had ] Number of particles smaller than 3, parameterisation not valid."
293 <<
" Doing Nothing");
298 <<
" with " << Npart <<
" outgoing particles " );
303 ATH_MSG_DEBUG(
"[ had ] create hadronic shower for particle with PDG ID "
304 << parent->pdgCode() <<
" and barcode "
327 << E <<
" | " << m <<
" | " << p <<
" | " );
331 ATH_MSG_VERBOSE(
"[ had ] interaction initiated by a secondary particle, no children saved " );
339 double chargedist = 0.;
340 std::vector<double>
charge(Npart);
341 std::vector<Trk::ParticleHypothesis> childType(Npart);
342 std::vector<double> newm(Npart);
343 std::vector<int> pdgid(Npart);
371 for (
int i=0; i<Npart; i++) {
373 if (chargedist<pif) {
380 if ( chargedist<2*pif) {
387 if (chargedist<3*pif) {
394 if (chargedist<3*pif+nef) {
401 if (chargedist<3*pif+nef+prf) {
415 if ( childType[0] != particle ) {
416 for (
int i=1; i<Npart; i++) {
417 if (childType[i]==particle) {
418 childType[i]=childType[0];
419 childType[0]=particle;
422 charge[0]=parent ? parent->charge() : cho;
449 std::vector<double> mom(Npart);
450 std::vector<double> th(Npart);
451 std::vector<double> ph(Npart);
454 double eps = 2./Npart;
456 mom[0] = 0.5*
pow(eps,
rnd);
463 Amg::Vector3D ptemp(mom[0]*sin(th[0])*cos(ph[0]),mom[0]*sin(th[0])*sin(ph[0]),mom[0]*cos(th[0]));
464 double ptot = mom[0];
467 for (
int i=1; i<Npart-2; i++) {
470 mom[i] = ( eps + CLHEP::RandFlat::shoot(
m_randomEngine)*(1-eps))*(1-ptot);
471 if (ptemp.mag()<1-ptot) {
472 while ( fabs(ptemp.mag()-mom[i])>1-ptot-mom[i] ){
473 mom[i] = ( eps + CLHEP::RandFlat::shoot(
m_randomEngine)*(1-eps))*(1-ptot);
477 double p_rem=1-ptot-mom[i];
478 double cthmax = fmin(1.,(-ptemp.mag()*ptemp.mag()-mom[i]*mom[i]+p_rem*p_rem)/2/ptemp.mag()/mom[i]);
484 HepGeom::Vector3D<double> dnewHep = HepGeom::RotateZ3D(ptemp.phi())*HepGeom::RotateY3D(ptemp.theta())*test;
488 ptemp += mom[i]*dnew;
494 mom[Npart-1] = 1-ptot-mom[Npart-2];
496 if (ptemp.mag()<1-ptot) {
497 while (mom[Npart-1]+mom[Npart-2]<ptemp.mag()) {
499 mom[Npart-1] = 1-ptot-mom[Npart-2];
502 if (ptemp.mag()<fabs(mom[Npart-1]-mom[Npart-2]) ) {
504 double sum = mom[Npart-1]-mom[Npart-2];
505 mom[Npart-2]=0.5*(sum+
diff);
506 mom[Npart-1]=0.5*(sum-
diff);
508 double cth =(-ptemp.mag()*ptemp.mag()-mom[Npart-2]*mom[Npart-2]+mom[Npart-1]*mom[Npart-1])/2/ptemp.mag()/mom[Npart-2];
509 if (fabs(cth)>1.) cth = (cth>0.) ? 1. : -1.;
514 HepGeom::Vector3D<double> dnewHep = HepGeom::RotateZ3D(ptemp.phi())*HepGeom::RotateY3D(ptemp.theta())*test;
517 th[Npart-2]=dnew.theta();
518 ph[Npart-2]=dnew.phi();
519 ptemp += mom[Npart-2]*dnew;
521 th[Npart-1]=dlast.theta();
522 ph[Npart-1]=dlast.phi();
527 for (
int i=0;i<Npart; i++) etot += sqrt(mom[i]*mom[i]+newm[i]*newm[i]);
529 for (
int i=0;i<Npart; i++) summ += newm[i];
533 float scale = sqrt(summ*summ+2*summ*p+m*m)/etot;
535 for (
int i=0;i<Npart; i++) {
537 etot += sqrt(mom[i]*mom[i]+newm[i]*newm[i]);
541 CLHEP::HepLorentzVector bv(p*particleDir.unit().x(),p*particleDir.unit().y(),p*particleDir.unit().z(),sqrt(etot*etot+p*p));
542 std::vector<CLHEP::HepLorentzVector> childBoost(Npart);
550 for (
int i=0; i<Npart; i++) {
551 Amg::Vector3D dirCms(sin(th[i])*cos(ph[i]),sin(th[i])*sin(ph[i]),cos(th[i]));
555 CLHEP::HepLorentzVector newp(childP.x(),childP.y(),childP.z(),sqrt(mom[i]*mom[i]+newm[i]*newm[i]));
556 CLHEP::HepLorentzVector childPB = newp.boost(bv.boostVector());
557 childBoost[i]=childPB;
568 ISF::ISFParticleVector::iterator childrenIt = children.begin();
569 unsigned short numChildren = 0;
571 for (
int i=0; i<Npart; i++) {
572 if (pdgid[i]<10000) {
576 eout += childBoost[i].e();
617 if (parent->getUserInformation()) validInfo->
setGeneration(parent->getUserInformation()->generation()+1);
623 ++childrenIt; numChildren++;
630 children.resize(numChildren);
653 ATH_MSG_VERBOSE(
"[ had ] it was kinematically possible to create " << gen_part <<
" shower particles " );
675 if (processSecondaries && !ispVec.empty() ) {
676 for (
auto *childParticle : ispVec) {
678 if (!childParticle->getTruthBinding()) {
679 ATH_MSG_ERROR(
"Could not retrieve TruthBinding from child ISFParticle "<< *childParticle);
695 return getHadState(parent, time, momentum.mag(), position, momentum.unit(), particle);
715 if (!ispVec.empty() ) {
716 for (
auto *childParticle : ispVec) {
718 if (!childParticle->getTruthBinding()) {
719 ATH_MSG_ERROR(
"Could not retrieve TruthBinding from child ISFParticle "<< *childParticle);
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
double charge(const T &p)
#define MAXHADINTCHILDREN
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
constexpr int pow(int base, int exp) noexcept
The generic ISF particle definition,.
void setUserInformation(ParticleUserInformation *userInfo)
Interface class for all truth incidents handled by the ISF.
void updateChildParticleProperties()
Update the id and particleLink properties of the child particles (to be called after registerTruthInc...
static ParticleClipboard & getInstance()
get the singleton instance
const ISF::ISFParticle * getParticle() const
get the particle from the clipboard
Each ISFParticle carries a pointer to this class.
void setGeneration(int gen)
void setProcess(int proc)
Material with information about thickness of material.
float thicknessInX0() const
Return the radiationlength fraction.
float thicknessInL0() const
Return the nuclear interaction length fraction.
float averageZ() const
Returns the average Z of the material.
float thickness() const
Return the thickness in mm.
A common object to be contained by.
float m_hadIntPointY
ntuple variable : hadronic interaction point y coordinate
ISF::ISFParticleVector getHadState(const ISF::ISFParticle *parent, double time, double p, const Amg::Vector3D &vertex, const Amg::Vector3D &particleDir, Trk::ParticleHypothesis particle) const
collect secondaries for layer material update
StatusCode finalize()
AlgTool finalize method.
float m_hadIntPointR
ntuple variable : hadronic interaction point r distance
int m_processCode
MCTruth process code for TruthIncidents created by this tool.
float m_hadIntPointX
ntuple variable : hadronic interaction point x coordinate
float m_hadIntChildEta[MAXHADINTCHILDREN]
nutple variable : hadronic interaction child eta
double m_minimumHadOutEnergy
hadronic interaction setting
ServiceHandle< ISF::ITruthSvc > m_truthRecordSvc
bool hadronicInteraction(const Amg::Vector3D &position, const Amg::Vector3D &momentum, double p, double E, double charge, const Trk::MaterialProperties &mprop, double pathCorrection, Trk::ParticleHypothesis particle=Trk::pion) const
interface for processing of the nuclear interactions
static double absorptionLength(const Trk::MaterialProperties *mat, double p, double q, Trk::ParticleHypothesis particle=Trk::pion)
interface for calculation of absorption length
int m_hadIntChildPdg[MAXHADINTCHILDREN]
nutple variable : hadronic interaction child Pdg
std::string m_hadIntValidationTreeFolder
stream/folder to for the TTree to be written out
int m_hadIntMotherBarcode
ntuple variable : hadronic interaction mother barcode
float m_hadIntPointZ
ntuple variable : hadronic interaction point z coordinate
TTree * m_hadIntValidationTree
Root Validation Tree.
ToolHandle< IPhysicsValidationTool > m_validationTool
ServiceHandle< IAtRndmGenSvc > m_rndGenSvc
Random Generator service.
float m_hadIntChildPcms[MAXHADINTCHILDREN]
nutple variable : hadronic interaction child Energy
float m_hadIntMotherEta
ntuple variable : hadronic interaction photon eta
bool doHadronicInteraction(double time, const Amg::Vector3D &position, const Amg::Vector3D &momentum, const Trk::Material *emat, Trk::ParticleHypothesis particle, bool processSecondaries) const
int m_hadIntMotherPdg
ntuple variable : hadronic interaction mother Pdg
float m_hadIntMotherPhi
ntuple variable : hadronic interaction mother phi
float m_hadIntChildPhi[MAXHADINTCHILDREN]
nutple variable : hadronic interaction child phi
std::string m_randomEngineName
Name of the random number stream.
float m_hadIntChildDeltaEta[MAXHADINTCHILDREN]
nutple variable : hadronic interaction child delta eta
ServiceHandle< ISF::IParticleBroker > m_particleBroker
ISF services & Tools.
std::string m_hadIntValidationTreeDescription
validation tree description - second argument in TTree
float m_hadIntMotherP
ntuple variable : hadronic interaction mother momentum
int m_hadIntChildren
nutple variable : hadronic interaction children numbers
float m_hadIntMotherPt
ntuple variable : hadronic interaction mother momentum
ISF::ISFParticleVector doHadIntOnLayer(const ISF::ISFParticle *parent, double time, const Amg::Vector3D &position, const Amg::Vector3D &momentum, const Trk::Material *emat, Trk::ParticleHypothesis particle) const
virtual ~HadIntProcessorParametric()
Destructor.
CLHEP::HepRandomEngine * m_randomEngine
Random engine.
HadIntProcessorParametric(const std::string &, const std::string &, const IInterface *)
AlgTool constructor for HadIntProcessorParametric.
std::string m_hadIntValidationTreeName
validation tree name - to be acessed by this from root
StatusCode initialize()
AlgTool initailize method.
float m_hadIntChildDeltaPhi[MAXHADINTCHILDREN]
nutple variable : hadronic interaction child delta phi
bool recordHadState(double time, double p, const Amg::Vector3D &vertex, const Amg::Vector3D &particleDir, Trk::ParticleHypothesis particle) const
interface for processing of the presampled nuclear interaction
float m_hadIntChildP[MAXHADINTCHILDREN]
nutple variable : hadronic interaction child Energy
double m_minimumHadInitialEnergy
float m_hadIntChildTh[MAXHADINTCHILDREN]
nutple variable : hadronic interaction child phi
float m_hadIntChildThc[MAXHADINTCHILDREN]
nutple variable : hadronic interaction child eta
float m_hadIntChildE
nutple variable : hadronic interaction children total energy
Eigen::Matrix< double, 3, 1 > Vector3D
constexpr int UNDEFINED_ID
constexpr int SIM_STATUS_THRESHOLD
Constant definiting the status threshold for simulated particles, eg. can be used to separate generat...
int generations(const T &p)
Method to return how many interactions a particle has undergone during simulation (TODO migrate to be...
std::vector< ISF::ISFParticle * > ISFParticleVector
ISFParticle vector.
constexpr double neutronMassInMeV
the mass of the neutron (in MeV)
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.