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 m_gendata = std::make_shared<GenData>();
40}
41
42//--------------------------------------------------------------------------
45
46//---------------------------------------------------------------------------
48
49 ++m_events;
50 ATH_MSG_DEBUG( "Event #" << m_events);
51
52 // clear up the vectors
53 m_fourPos.clear();
54 m_fourMom.clear();
55 m_polarization.clear();
56 m_pdgCode.clear();
57
58 const EventContext& ctx = Gaudi::Hive::currentContext();
59 CLHEP::HepRandomEngine* rndmEngine = this->getRandomEngine(name(), ctx);
60
61 const TrackRecordCollection* coll = nullptr;
62 CHECK( evtStore()->retrieve(coll,m_recordName) );
63
64 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");
65
66 for (const auto & iterTTR : *coll) {
67
68 const auto pmass = m_gendata->particleMass(std::abs(iterTTR.GetPDGCode()));
69 double mass = *pmass;
70 double en = std::sqrt(mass*mass+iterTTR.GetMomentum().mag2());
71
72 ATH_MSG_VERBOSE("Reading back TTR:\n pos is "<<iterTTR.GetPosition()
73 <<"\n mom is "<<iterTTR.GetMomentum()
74 <<"\n pdg is "<<iterTTR.GetPDGCode() );
75
76 CLHEP::HepLorentzVector particle4Position( iterTTR.GetPosition(), iterTTR.GetTime());
77
78 ATH_MSG_DEBUG( "Smearing position by up to " << m_smearTR << " mm and momentum by up to " << m_smearTRp << " radians" );
79 if (m_smearTR>0){
80 ATH_MSG_DEBUG( "Track record started at " << particle4Position );
81
82 // if Z is maximal, move in X and Y; otherwise move in Z and "phi"
83 if ( particle4Position.z() == 22031 || particle4Position.z() == -22031 ){ //FIXME Hardcoded limits!
84 particle4Position.setX( particle4Position.x() + CLHEP::RandFlat::shoot(rndmEngine, -m_smearTR, m_smearTR) );
85 particle4Position.setY( particle4Position.y() + CLHEP::RandFlat::shoot(rndmEngine, -m_smearTR, m_smearTR) );
86 } else {
87 particle4Position.setZ( particle4Position.z() + CLHEP::RandFlat::shoot(rndmEngine, -m_smearTR, m_smearTR) );
88 double R = std::sqrt( std::pow( particle4Position.x(),2 ) + std::pow(particle4Position.y(),2 ) );
89 double dPhi = std::atan2( m_smearTR, R );
90 dPhi = CLHEP::RandFlat::shoot( rndmEngine, -dPhi, dPhi );
91 double theta = std::atan2( particle4Position.x() , particle4Position.y() );
92 particle4Position.setX( R*std::sin( theta + dPhi ) );
93 particle4Position.setY( R*std::cos( theta + dPhi ) );
94 }
95 ATH_MSG_DEBUG( "Shifted track record to " << particle4Position );
96 }
97 CLHEP::HepLorentzVector particle4Momentum( iterTTR.GetMomentum(), en );
98 if (m_smearTRp>0){
99 ATH_MSG_DEBUG( "Track record momentum was " << particle4Momentum );
100
101 // Keep p - smear an angle, and then randomly spin that change in (0,2PI)
102 double dTheta = CLHEP::RandFlat::shoot(rndmEngine, 0, m_smearTRp);
103 double dPhi = CLHEP::RandFlat::shoot(rndmEngine, 0, 2*M_PI);
104
105 // Need a perpendicular vector...
106 CLHEP::HepLorentzVector perpendicularMomentum( 1 , 0 , 0 , 0);
107 if ( particle4Momentum.x() != 0 ){
108 if (particle4Momentum.y() == 0){
109 perpendicularMomentum.setX( 0 );
110 perpendicularMomentum.setY( 1 );
111 } else {
112 perpendicularMomentum.setX( particle4Momentum.y() );
113 perpendicularMomentum.setY( particle4Momentum.x() );
114 }
115 }
116
117 // Now scale it based on dTheta
118 double tempP = std::pow(particle4Momentum.x(),2)+std::pow(particle4Momentum.y(),2)+std::pow(particle4Momentum.z(),2);
119 if ( tempP==0 ) {
120 ATH_MSG_DEBUG("Our initial momentum had zero magnitude!!");
121 perpendicularMomentum.setX(0);
122 perpendicularMomentum.setY(0);
123 } else if ( std::tan(dTheta) == 0 ){
124 ATH_MSG_DEBUG("Randomly deciding to keep the vector's direction...");
125 perpendicularMomentum.setX(0);
126 perpendicularMomentum.setY(0);
127 } else {
128 double scale = ( tempP ) * std::sin(dTheta) / ( std::pow(perpendicularMomentum.x(),2)+std::pow(perpendicularMomentum.y(),2) );
129 perpendicularMomentum.setX( perpendicularMomentum.x() * scale );
130 perpendicularMomentum.setY( perpendicularMomentum.y() * scale );
131
132 // Rotate perpendicularMomentum by dPhi around particle4Momentum
133 perpendicularMomentum.rotate( dPhi , particle4Momentum.vect() );
134 }
135 particle4Momentum.setX( particle4Momentum.x() + perpendicularMomentum.x() );
136 particle4Momentum.setY( particle4Momentum.y() + perpendicularMomentum.y() );
137 particle4Momentum.setZ( particle4Momentum.z() + perpendicularMomentum.z() );
138
139 // Rescale (very small effect, but want to include it)
140 double scale2 = tempP==0? 1 : (pow(particle4Momentum.x(),2)+pow(particle4Momentum.y(),2)+pow(particle4Momentum.z(),2)) / tempP;
141 particle4Momentum.setX( particle4Momentum.x() * scale2 );
142 particle4Momentum.setY( particle4Momentum.y() * scale2 );
143 particle4Momentum.setZ( particle4Momentum.z() * scale2 );
144 ATH_MSG_DEBUG( "Rotated the vector by " << perpendicularMomentum );
145 ATH_MSG_DEBUG( "And resulting momentum is " << particle4Momentum );
146 }
147 if (m_stopParticles){
148 ATH_MSG_DEBUG( "Will stop the track record where it is and give it mass " << mass );
149 particle4Momentum.setX(0);
150 particle4Momentum.setY(0);
151 particle4Momentum.setZ(0);
152 particle4Momentum.setT(mass);
153
154 double settime=CLHEP::RandFlat::shoot(rndmEngine,m_stopped_tminus, m_stopped_tplus);
155 ATH_MSG_DEBUG( "Setting particle time to something uniform between "<<m_stopped_tminus<<" and "<<m_stopped_tplus<<" ns : " << settime );
156 if (m_add_cL){
157 settime += particle4Position.rho()/CLHEP::c_light;
158 }
159 particle4Position.setT(settime*CLHEP::c_light); // ct in mm
160 }
161
162 m_fourPos.push_back( particle4Position );
163 m_fourMom.push_back( particle4Momentum );
164
165 m_pdgCode.push_back(iterTTR.GetPDGCode());
166 HepMC::Polarization thePolarization(0.0,0.0);
167 m_polarization.push_back(thePolarization);
168
169 if (m_stopParticles){
170 ATH_MSG_DEBUG( "Only one per event!!" );
171 break;
172 }
173 } // Loop through the track record collection
174
175 return StatusCode::SUCCESS;
176}
177
178//---------------------------------------------------------------------------
180
181 if ( m_fourMom.size() != m_fourPos.size() || m_fourMom.size() != m_polarization.size()) {
182 ATH_MSG_ERROR("Wrong different number of vertexes/momenta/polaritazions!");
183 return StatusCode::FAILURE;
184 }
185 for(std::size_t v = 0; v < m_fourMom.size(); ++v){
186 // Note: The vertex and particle are owned by the event, so the
187 // event is responsible for those pointers.
188
189 // Create the particle, and specify its polarization.
191
192 // Create the vertex, and add the particle to the vertex.
194 vertex->add_particle_out( particle );
195
196 // Add the vertex to the event.
197 event->add_vertex( std::move(vertex) );
198
199 // Add attributes
201 } // Loop over the particles
202
203 event->set_event_number(m_events); // Set the event number
204 if (event->weights().empty()){
205 event->weights().push_back(1.0);
206 }
207 return StatusCode::SUCCESS;
208}
209
#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
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
size_type size() const
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.
std::shared_ptr< GenData > m_gendata
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)
HepMC3::FourVector FourVector
GenParticlePtr newGenParticlePtr(const HepMC3::FourVector &mom=HepMC3::FourVector::ZERO_VECTOR(), int pid=0, int status=0)
Definition GenParticle.h:21
HepMC3::GenParticlePtr GenParticlePtr
Definition GenParticle.h:19
GenVertexPtr newGenVertexPtr(const HepMC3::FourVector &pos=HepMC3::FourVector::ZERO_VECTOR(), const int i=0)
Definition GenVertex.h:25
HepMC3::GenVertexPtr GenVertexPtr
Definition GenVertex.h:23
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39