ATLAS Offline Software
Loading...
Searching...
No Matches
TrackRecordGenerator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// -------------------------------------------------------------
6// File: TrackRecordGenerator/TrackRecordGenerator.cxx
7// Mostly adopted from the cosmic generator
8
10
11#include "CLHEP/Vector/ThreeVector.h"
12#include "CLHEP/Geometry/Normal3D.h"
13#include "CLHEP/Units/PhysicalConstants.h"
14#include "CLHEP/Random/RandFlat.h"
15
17
18#include <limits>
19#include <cmath>
20#include <vector>
21#include <string>
22#include <fstream>
23
24//--------------------------------------------------------------------------
25TrackRecordGenerator::TrackRecordGenerator(const std::string& name, ISvcLocator* pSvcLocator)
26 : GenModule(name,pSvcLocator)
27 , m_events(0)
28{
29 // Input collection name
30 declareProperty("TRCollection" , m_recordName = "CosmicRecord" );
31
32 // Smearing of the initial position for tracks
33 declareProperty("TRSmearing", m_smearTR=-1, "Smear the initial position of the track by up to this amount");
34 declareProperty("TRPSmearing", m_smearTRp=-1, "Smear the momentum of the track by up to this amount");
35 declareProperty("StopParticles", m_stopParticles=false, "Stop the particles and make them decay within 25 ns");
36 declareProperty("stopped_tminus", m_stopped_tminus =-25. );
37 declareProperty("stopped_tplus", m_stopped_tplus =25. );
38 declareProperty("Add_cL", m_add_cL=true, "For stopped particles, shift the time by c times the decay rho");
39}
40
41//--------------------------------------------------------------------------
44
45//---------------------------------------------------------------------------
47
48 ++m_events;
49 ATH_MSG_DEBUG( "Event #" << m_events);
50
51 // clear up the vectors
52 m_fourPos.clear();
53 m_fourMom.clear();
54 m_polarization.clear();
55 m_pdgCode.clear();
56
57 const EventContext& ctx = Gaudi::Hive::currentContext();
58 CLHEP::HepRandomEngine* rndmEngine = this->getRandomEngine(name(), ctx);
59
60 const TrackRecordCollection* coll = nullptr;
61 CHECK( evtStore()->retrieve(coll,m_recordName) );
62
63 ATH_MSG_INFO("retrieved "<<coll->size()<<" TTR hits; will smear position by "<< (m_smearTR>0?m_smearTR:0.) <<" mm and momentum by "<< (m_smearTRp>0?m_smearTRp:0.) <<" radians");
64
65 for (const auto & iterTTR : *coll) {
66
67 const HepPDT::ParticleData* particle = particleData(std::abs(iterTTR.GetPDGCode()));
68 double mass = particle->mass().value();
69 double en = std::sqrt(mass*mass+iterTTR.GetMomentum().mag2());
70
71 ATH_MSG_VERBOSE("Reading back TTR:\n pos is "<<iterTTR.GetPosition()
72 <<"\n mom is "<<iterTTR.GetMomentum()
73 <<"\n pdg is "<<iterTTR.GetPDGCode() );
74
75 CLHEP::HepLorentzVector particle4Position( iterTTR.GetPosition(), iterTTR.GetTime());
76
77 ATH_MSG_DEBUG( "Smearing position by up to " << m_smearTR << " mm and momentum by up to " << m_smearTRp << " radians" );
78 if (m_smearTR>0){
79 ATH_MSG_DEBUG( "Track record started at " << particle4Position );
80
81 // if Z is maximal, move in X and Y; otherwise move in Z and "phi"
82 if ( particle4Position.z() == 22031 || particle4Position.z() == -22031 ){ //FIXME Hardcoded limits!
83 particle4Position.setX( particle4Position.x() + CLHEP::RandFlat::shoot(rndmEngine, -m_smearTR, m_smearTR) );
84 particle4Position.setY( particle4Position.y() + CLHEP::RandFlat::shoot(rndmEngine, -m_smearTR, m_smearTR) );
85 } else {
86 particle4Position.setZ( particle4Position.z() + CLHEP::RandFlat::shoot(rndmEngine, -m_smearTR, m_smearTR) );
87 double R = std::sqrt( std::pow( particle4Position.x(),2 ) + std::pow(particle4Position.y(),2 ) );
88 double dPhi = std::atan2( m_smearTR, R );
89 dPhi = CLHEP::RandFlat::shoot( rndmEngine, -dPhi, dPhi );
90 double theta = std::atan2( particle4Position.x() , particle4Position.y() );
91 particle4Position.setX( R*std::sin( theta + dPhi ) );
92 particle4Position.setY( R*std::cos( theta + dPhi ) );
93 }
94 ATH_MSG_DEBUG( "Shifted track record to " << particle4Position );
95 }
96 CLHEP::HepLorentzVector particle4Momentum( iterTTR.GetMomentum(), en );
97 if (m_smearTRp>0){
98 ATH_MSG_DEBUG( "Track record momentum was " << particle4Momentum );
99
100 // Keep p - smear an angle, and then randomly spin that change in (0,2PI)
101 double dTheta = CLHEP::RandFlat::shoot(rndmEngine, 0, m_smearTRp);
102 double dPhi = CLHEP::RandFlat::shoot(rndmEngine, 0, 2*M_PI);
103
104 // Need a perpendicular vector...
105 CLHEP::HepLorentzVector perpendicularMomentum( 1 , 0 , 0 , 0);
106 if ( particle4Momentum.x() != 0 ){
107 if (particle4Momentum.y() == 0){
108 perpendicularMomentum.setX( 0 );
109 perpendicularMomentum.setY( 1 );
110 } else {
111 perpendicularMomentum.setX( particle4Momentum.y() );
112 perpendicularMomentum.setY( particle4Momentum.x() );
113 }
114 }
115
116 // Now scale it based on dTheta
117 double tempP = std::pow(particle4Momentum.x(),2)+std::pow(particle4Momentum.y(),2)+std::pow(particle4Momentum.z(),2);
118 if ( tempP==0 ) {
119 ATH_MSG_DEBUG("Our initial momentum had zero magnitude!!");
120 perpendicularMomentum.setX(0);
121 perpendicularMomentum.setY(0);
122 } else if ( std::tan(dTheta) == 0 ){
123 ATH_MSG_DEBUG("Randomly deciding to keep the vector's direction...");
124 perpendicularMomentum.setX(0);
125 perpendicularMomentum.setY(0);
126 } else {
127 double scale = ( tempP ) * std::sin(dTheta) / ( std::pow(perpendicularMomentum.x(),2)+std::pow(perpendicularMomentum.y(),2) );
128 perpendicularMomentum.setX( perpendicularMomentum.x() * scale );
129 perpendicularMomentum.setY( perpendicularMomentum.y() * scale );
130
131 // Rotate perpendicularMomentum by dPhi around particle4Momentum
132 perpendicularMomentum.rotate( dPhi , particle4Momentum.vect() );
133 }
134 particle4Momentum.setX( particle4Momentum.x() + perpendicularMomentum.x() );
135 particle4Momentum.setY( particle4Momentum.y() + perpendicularMomentum.y() );
136 particle4Momentum.setZ( particle4Momentum.z() + perpendicularMomentum.z() );
137
138 // Rescale (very small effect, but want to include it)
139 double scale2 = tempP==0? 1 : (pow(particle4Momentum.x(),2)+pow(particle4Momentum.y(),2)+pow(particle4Momentum.z(),2)) / tempP;
140 particle4Momentum.setX( particle4Momentum.x() * scale2 );
141 particle4Momentum.setY( particle4Momentum.y() * scale2 );
142 particle4Momentum.setZ( particle4Momentum.z() * scale2 );
143 ATH_MSG_DEBUG( "Rotated the vector by " << perpendicularMomentum );
144 ATH_MSG_DEBUG( "And resulting momentum is " << particle4Momentum );
145 }
146 if (m_stopParticles){
147 ATH_MSG_DEBUG( "Will stop the track record where it is and give it mass " << mass );
148 particle4Momentum.setX(0);
149 particle4Momentum.setY(0);
150 particle4Momentum.setZ(0);
151 particle4Momentum.setT(mass);
152
153 double settime=CLHEP::RandFlat::shoot(rndmEngine,m_stopped_tminus, m_stopped_tplus);
154 ATH_MSG_DEBUG( "Setting particle time to something uniform between "<<m_stopped_tminus<<" and "<<m_stopped_tplus<<" ns : " << settime );
155 if (m_add_cL){
156 settime += particle4Position.rho()/CLHEP::c_light;
157 }
158 particle4Position.setT(settime*CLHEP::c_light); // ct in mm
159 }
160
161 m_fourPos.push_back( particle4Position );
162 m_fourMom.push_back( particle4Momentum );
163
164 m_pdgCode.push_back(iterTTR.GetPDGCode());
165 HepMC::Polarization thePolarization(0.0,0.0);
166 m_polarization.push_back(thePolarization);
167
168 if (m_stopParticles){
169 ATH_MSG_DEBUG( "Only one per event!!" );
170 break;
171 }
172 } // Loop through the track record collection
173
174 return StatusCode::SUCCESS;
175}
176
177//---------------------------------------------------------------------------
178StatusCode TrackRecordGenerator::fillEvt(HepMC::GenEvent* event) {
179
180 if ( m_fourMom.size() != m_fourPos.size() || m_fourMom.size() != m_polarization.size()) {
181 ATH_MSG_ERROR("Wrong different number of vertexes/momenta/polaritazions!");
182 return StatusCode::FAILURE;
183 }
184 for(std::size_t v = 0; v < m_fourMom.size(); ++v){
185 // Note: The vertex and particle are owned by the event, so the
186 // event is responsible for those pointers.
187
188 // Create the particle, and specify its polarization.
189 HepMC::GenParticlePtr particle = HepMC::newGenParticlePtr( HepMC::FourVector(m_fourMom[v].x(),m_fourMom[v].y(),m_fourMom[v].z(),m_fourMom[v].t()), m_pdgCode[v], 1);
190
191 // Create the vertex, and add the particle to the vertex.
192 HepMC::GenVertexPtr vertex = HepMC::newGenVertexPtr(HepMC::FourVector(m_fourPos[v].x(),m_fourPos[v].y(),m_fourPos[v].z(),m_fourPos[v].t()));
193 vertex->add_particle_out( particle );
194
195 // Add the vertex to the event.
196 event->add_vertex( std::move(vertex) );
197
198 // Add attributes
200 } // Loop over the particles
201
202 event->set_event_number(m_events); // Set the event number
203 if (event->weights().empty()){
204 event->weights().push_back(1.0);
205 }
206 return StatusCode::SUCCESS;
207}
208
#define M_PI
Scalar theta() const
theta method
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
#define scale2
AtlasHitsVector< TrackRecord > TrackRecordCollection
#define y
#define x
#define z
constexpr int pow(int base, int exp) noexcept
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
size_type size() const
const HepPDT::ParticleData * particleData(int pid) const
Access an element in the particle data table.
Definition GenBase.h:126
GenModule(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
Definition GenModule.cxx:14
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
Definition GenModule.cxx:34
bool m_stopParticles
Stop particles before simulation.
double m_smearTR
Amount by which to smear TR position.
virtual StatusCode fillEvt(HepMC::GenEvent *evt)
For filling the HepMC event object.
float m_stopped_tplus
Bounds for random time.
std::vector< CLHEP::HepLorentzVector > m_fourMom
std::vector< HepMC::Polarization > m_polarization
std::vector< CLHEP::HepLorentzVector > m_fourPos
std::string m_recordName
TrackRecord collection name.
std::vector< int > m_pdgCode
TrackRecordGenerator(const std::string &name, ISvcLocator *pSvcLocator)
double m_smearTRp
Amount by which to smear TR momentum.
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
bool m_add_cL
For stopped particles, add c*L to the time.
void set_polarization(T &a, const Polarization &b)
HepMC::GenVertex * GenVertexPtr
Definition GenVertex.h:59
GenVertexPtr newGenVertexPtr(const HepMC::FourVector &pos=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), const int i=0)
Definition GenVertex.h:64
GenParticlePtr newGenParticlePtr(const HepMC::FourVector &mom=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), int pid=0, int status=0)
Definition GenParticle.h:39
GenParticle * GenParticlePtr
Definition GenParticle.h:37