ATLAS Offline Software
TrackRecordGenerator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 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 //--------------------------------------------------------------------------
25 TrackRecordGenerator::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 //--------------------------------------------------------------------------
43 {}
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 (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 //---------------------------------------------------------------------------
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.
190 
191  // Create the vertex, and add the particle to the vertex.
193  vertex->add_particle_out( particle );
194 
195  // Add the vertex to the event.
196  event->add_vertex( 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 
HepMC::GenVertexPtr
HepMC::GenVertex * GenVertexPtr
Definition: GenVertex.h:59
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
TrackRecordGenerator::~TrackRecordGenerator
virtual ~TrackRecordGenerator()
Definition: TrackRecordGenerator.cxx:42
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
scale2
#define scale2
Definition: JetAttributeHisto.cxx:42
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
Base_Fragment.mass
mass
Definition: Sherpa_i/share/common/Base_Fragment.py:59
TrackRecordGenerator.h
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
TrackRecordGenerator::m_smearTR
double m_smearTR
Amount by which to smear TR position.
Definition: TrackRecordGenerator.h:45
theta
Scalar theta() const
theta method
Definition: AmgMatrixBasePlugin.h:75
HepMC::GenParticlePtr
GenParticle * GenParticlePtr
Definition: GenParticle.h:37
AtlasHitsVector
Definition: AtlasHitsVector.h:33
M_PI
#define M_PI
Definition: ActiveFraction.h:11
HepMC::set_polarization
void set_polarization(T &a, const Polarization &b)
Definition: Polarization.h:44
TrackRecordGenerator::m_pdgCode
std::vector< int > m_pdgCode
Definition: TrackRecordGenerator.h:38
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
TrackRecordGenerator::m_recordName
std::string m_recordName
TrackRecord collection name.
Definition: TrackRecordGenerator.h:47
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
x
#define x
TrackRecordGenerator::fillEvt
virtual StatusCode fillEvt(HepMC::GenEvent *evt)
For filling the HepMC event object.
Definition: TrackRecordGenerator.cxx:178
GenModule::getRandomEngine
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
Definition: GenModule.cxx:34
TrackRecordGenerator::m_fourPos
std::vector< CLHEP::HepLorentzVector > m_fourPos
Definition: TrackRecordGenerator.h:39
TrackRecordGenerator::m_stopParticles
bool m_stopParticles
Stop particles before simulation.
Definition: TrackRecordGenerator.h:48
TrackRecordGenerator::m_polarization
std::vector< HepMC::Polarization > m_polarization
Definition: TrackRecordGenerator.h:42
GenModule
Base class for common behaviour of generator interfaces.
Definition: GenModule.h:39
AthCommonDataStore< AthCommonMsg< Algorithm > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
HepMC::newGenVertexPtr
GenVertexPtr newGenVertexPtr(const HepMC::FourVector &pos=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), const int i=0)
Definition: GenVertex.h:64
z
#define z
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TauGNNUtils::Variables::Track::dPhi
bool dPhi(const xAOD::TauJet &tau, const xAOD::TauTrack &track, double &out)
Definition: TauGNNUtils.cxx:538
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
AnalysisUtils::Delta::R
double R(const INavigable4Momentum *p1, const double v_eta, const double v_phi)
Definition: AnalysisMisc.h:49
TrackRecordGenerator::TrackRecordGenerator
TrackRecordGenerator(const std::string &name, ISvcLocator *pSvcLocator)
Definition: TrackRecordGenerator.cxx:25
TrackRecordGenerator::m_events
int m_events
Definition: TrackRecordGenerator.h:37
TrackRecordGenerator::m_fourMom
std::vector< CLHEP::HepLorentzVector > m_fourMom
Definition: TrackRecordGenerator.h:40
TrackRecordGenerator::m_stopped_tminus
float m_stopped_tminus
Definition: TrackRecordGenerator.h:49
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
PlotCalibFromCool.en
en
Definition: PlotCalibFromCool.py:399
TrackRecordCollection.h
TrackRecordGenerator::m_stopped_tplus
float m_stopped_tplus
Bounds for random time.
Definition: TrackRecordGenerator.h:49
python.PhysicalConstants.c_light
float c_light
Definition: PhysicalConstants.py:63
python.PyAthena.v
v
Definition: PyAthena.py:154
Trk::vertex
@ vertex
Definition: MeasurementType.h:21
HepMC::newGenParticlePtr
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
y
#define y
TrackRecordGenerator::callGenerator
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
Definition: TrackRecordGenerator.cxx:46
AtlasHitsVector::size
size_type size() const
Definition: AtlasHitsVector.h:143
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
GenBase::particleData
const HepPDT::ParticleData * particleData(int pid) const
Access an element in the particle data table.
Definition: GenBase.h:126
TrackRecordGenerator::m_smearTRp
double m_smearTRp
Amount by which to smear TR momentum.
Definition: TrackRecordGenerator.h:46
TrackRecordGenerator::m_add_cL
bool m_add_cL
For stopped particles, add c*L to the time.
Definition: TrackRecordGenerator.h:50