ATLAS Offline Software
GenEventBeamEffectBooster.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // class header include
7 
8 // Athena includes
10 #include "CLHEP/Random/RandGaussZiggurat.h"
11 
12 // CLHEP includes
13 #include "CLHEP/Vector/LorentzVector.h"
14 #include "CLHEP/Units/PhysicalConstants.h"
15 
16 // HepMC includes
17 #include "AtlasHepMC/GenEvent.h"
18 #include "AtlasHepMC/GenParticle.h"
19 
20 namespace Simulation
21 {
24  const std::string& n,
25  const IInterface* p )
26  : base_class(t,n,p)
27  {
28  }
29 
30 
33  {
34  ATH_MSG_VERBOSE("Initializing ...");
35  // prepare the RandonNumber generation
36  ATH_CHECK(m_rndGenSvc.retrieve());
37  m_randomEngine = m_rndGenSvc->getEngine(this, m_randomEngineName); //FIXME
38  if (!m_randomEngine) {
39  ATH_MSG_ERROR("Could not get random number engine from RandomNumberService. Abort.");
40  return StatusCode::FAILURE;
41  }
42  return StatusCode::SUCCESS;
43  }
44 
45 
48  {
49  ATH_MSG_VERBOSE("Finalizing ...");
50  return StatusCode::SUCCESS;
51  }
52 
54  {
55  // Refresh properties retrieved from the BeamCondSvc here if
56  // necessary. It may be more thread-safe to retrieve them directly
57  // from the BeamCondSvc during initializeGenEvent though?
58 
59  // m_sigma_px_b1 = 20.E-6; // angular divergence in x of beam 1 [rad]
60  // m_sigma_px_b2 = 21.E-6; // angular divergence in x of beam 2 [rad]
61  // m_sigma_py_b1 = 22.E-6; // angular divergence in y of beam 1 [rad]
62  // m_sigma_py_b2 = 23.E-6; // angular divergence in y of beam 2 [rad]
63  // // Crossing angles, note the convention here is taken from online https://atlas-dcs.cern.ch/index.php?page=LHC_INS::INS_BPM
64  // m_xing_x_b1 = 19.E-6; // half-crossing in x for beam 1 at IP1, i.e. angle between beam 1 and z-axis
65  // m_xing_x_b2 = 1.E-6; // half-crossing in x for beam 2 at IP1, i.e. angle between beam 2 and z-axis
66  // m_xing_y_b1 = 150.E-6; // half-crossing in y for beam 1 at IP1, i.e. angle between beam 1 and z-axis
67  // m_xing_y_b2 = -152.E-6; // half-crossing in y for beam 2 at IP1, i.e. angle between beam 2 and z-axis
68  // m_dE = 1.1E-4; // Delta_E/E theoretical value
69  // m_pbeam1 = 3500.0E3; /// @todo Get from a service
70  // m_pbeam2 = 3500.0E3; /// @todo Get from a service
71  // m_beam1ParticleMass = CLHEP::proton_mass_c2;
72  // m_beam2ParticleMass = CLHEP::proton_mass_c2;
73 
74  return StatusCode::SUCCESS;
75  }
76 
77  StatusCode GenEventBeamEffectBooster::initializeGenEvent(CLHEP::HepLorentzRotation& transform, const EventContext& ctx) const
78  {
79  // Reset the transformation
80  transform = CLHEP::HepLorentzRotation(); //TODO drop this
81 
82  // Prepare the random engine
83  m_randomEngine->setSeed( name(), ctx );
84  CLHEP::HepRandomEngine* randomEngine(m_randomEngine->getEngine(ctx));
85 
86  // Create beam 1 and 2 momenta, including divergence and crossing-angle effects
87  const double px1 = m_pbeam1 * CLHEP::RandGaussZiggurat::shoot(randomEngine, m_xing_x_b2, m_sigma_px_b2);
88  const double py1 = m_pbeam1 * CLHEP::RandGaussZiggurat::shoot(randomEngine, m_xing_y_b2, m_sigma_py_b2);
89  const double pz1 = CLHEP::RandGaussZiggurat::shoot(randomEngine, sqrt(m_pbeam1*m_pbeam1 - px1*px1 - py1*py1), m_dE);
90  const double e1 = sqrt(px1*px1 + py1*py1 + pz1*pz1 + m_beam1ParticleMass*m_beam1ParticleMass);
91  CLHEP::HepLorentzVector pp1(px1, py1, pz1, e1);
92 
93  const double px2 = -m_pbeam2 * CLHEP::RandGaussZiggurat::shoot(randomEngine, m_xing_x_b1, m_sigma_px_b1); // crossing angle & divergence
94  const double py2 = -m_pbeam2 * CLHEP::RandGaussZiggurat::shoot(randomEngine, m_xing_y_b1, m_sigma_py_b1);
95  const double pz2 = CLHEP::RandGaussZiggurat::shoot(randomEngine, -sqrt(m_pbeam2*m_pbeam2 - px2*px2 - py2*py2), m_dE); // longitudinal component in + direction energy smeared
96  const double e2 = sqrt(px2*px2 + py2*py2 + pz2*pz2 + m_beam2ParticleMass*m_beam2ParticleMass);
97  CLHEP::HepLorentzVector pp2(px2, py2, pz2, e2);
98 
99  // Now set-up rotation-boost matrix
100  const CLHEP::HepLorentzVector psum = pp1 + pp2;
101  const CLHEP::HepLorentzVector& dir = pp1;
102  // Boost psum back on the direction of dir, adapted from bstback & fromCMframe PYTHIA8, credit to T.Sjostrand
103  const double betaX = -psum.x() / psum.t();
104  const double betaY = -psum.y() / psum.t();
105  const double betaZ = -psum.z() / psum.t();
106  const double beta2 = betaX*betaX + betaY*betaY + betaZ*betaZ;
107  const double gamma = 1. / sqrt(1. - beta2);
108  const double prod1 = betaX * dir.x() + betaY * dir.y() + betaZ * dir.z();
109  const double prod2 = gamma * (gamma * prod1 / (1. + gamma) + dir.t());
110  // Get the angle of rotation
111  const CLHEP::HepLorentzVector back(dir.x() + prod2 * betaX,
112  dir.y() + prod2 * betaY,
113  dir.z() + prod2 * betaZ,
114  gamma * (dir.t() + prod1));
115  const double thback = back.theta();
116  const double phback = back.phi();
117  // Setting up two rotation matrices, via 3x3 rep. rather than even more messy EulerAngles
118  const double sph = sin(phback), cph = cos(phback), sth = sin(thback), cth = cos(thback);
119  const CLHEP::HepRotation rot1(CLHEP::HepRep3x3(cph, sph, 0.0, -sph, cph, 0.0, 0.0, 0.0, 1.0));
120  const CLHEP::HepRotation rot2(CLHEP::HepRep3x3(cth*cph, -sph, sth*cph, cth*sph, cph, sth*sph, -sth, 0.0, cth));
121  const CLHEP::HepBoost bst(psum.px()/psum.e(), psum.py()/psum.e(), psum.pz()/psum.e());
122  // Combine the two rotations and the boost; matrix multiplication order matters
123  const CLHEP::HepRotation rot = rot2*rot1;
125  transform.set(rot,bst);
126  }
127  else {
128  if(m_applyBoost) {
129  transform.set(bst);
130  }
131  if(m_applyDivergence) {
132  transform.set(rot);
133  }
134  }
135  return StatusCode::SUCCESS;
136  }
137 
139  StatusCode GenEventBeamEffectBooster::manipulate(HepMC::GenEvent& ge, const EventContext& ctx) const
140  {
141  // Obtain the transformation
142  CLHEP::HepLorentzRotation transform = CLHEP::HepLorentzRotation();
144 
145  for( auto particleIter: ge) {
146  this->boostParticle(particleIter, transform);
147  }
148  return StatusCode::SUCCESS;
149  }
150 
152  const CLHEP::HepLorentzRotation& transform) const
153  {
154  // Apply the same transformation for EVERY HepMC::GenParticle
155  const HepMC::FourVector &mom = p->momentum();
156  CLHEP::HepLorentzVector hv(mom.px(), mom.py(), mom.pz(), mom.e()); //TODO check units
157  ATH_MSG_VERBOSE("BEAMBOOST initial momentum " << hv );
158  hv.transform(transform);
159  ATH_MSG_VERBOSE("BEAMBOOST transformed momentum " << hv);
160  p->set_momentum(HepMC::FourVector(hv.px(),hv.py(),hv.pz(),hv.e())); //TODO check units
161  }
162 
163 }
Simulation::GenEventBeamEffectBooster::m_pbeam1
Gaudi::Property< double > m_pbeam1
Definition: GenEventBeamEffectBooster.h:76
GenEvent.h
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
Simulation::GenEventBeamEffectBooster::m_xing_x_b2
Gaudi::Property< double > m_xing_x_b2
Definition: GenEventBeamEffectBooster.h:72
egammaEnergyPositionAllSamples::e1
double e1(const xAOD::CaloCluster &cluster)
return the uncorrected cluster energy in 1st sampling
HepMC::GenParticlePtr
GenParticle * GenParticlePtr
Definition: GenParticle.h:37
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
Simulation::GenEventBeamEffectBooster::initializeAthenaEvent
StatusCode initializeAthenaEvent()
Definition: GenEventBeamEffectBooster.cxx:53
Simulation::GenEventBeamEffectBooster::initializeGenEvent
StatusCode initializeGenEvent(CLHEP::HepLorentzRotation &transform, const EventContext &ctx) const
calculate the transformations that we want to apply to the particles in the current GenEvent
Definition: GenEventBeamEffectBooster.cxx:77
Simulation::GenEventBeamEffectBooster::m_dE
Gaudi::Property< double > m_dE
Definition: GenEventBeamEffectBooster.h:75
GenParticle.h
Simulation::GenEventBeamEffectBooster::m_xing_x_b1
Gaudi::Property< double > m_xing_x_b1
Definition: GenEventBeamEffectBooster.h:71
Simulation::GenEventBeamEffectBooster::m_sigma_px_b1
Gaudi::Property< double > m_sigma_px_b1
Definition: GenEventBeamEffectBooster.h:66
Simulation::GenEventBeamEffectBooster::m_beam1ParticleMass
Gaudi::Property< double > m_beam1ParticleMass
Definition: GenEventBeamEffectBooster.h:78
GenEventBeamEffectBooster.h
Simulation::GenEventBeamEffectBooster::m_xing_y_b1
Gaudi::Property< double > m_xing_y_b1
Definition: GenEventBeamEffectBooster.h:73
ParticleGun_EoverP_Config.mom
mom
Definition: ParticleGun_EoverP_Config.py:63
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
TrigVtx::gamma
@ gamma
Definition: TrigParticleTable.h:26
Simulation::GenEventBeamEffectBooster::initialize
StatusCode initialize() override final
Athena algtool's Hooks.
Definition: GenEventBeamEffectBooster.cxx:32
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
Simulation::GenEventBeamEffectBooster::m_xing_y_b2
Gaudi::Property< double > m_xing_y_b2
Definition: GenEventBeamEffectBooster.h:74
Simulation::GenEventBeamEffectBooster::m_sigma_py_b2
Gaudi::Property< double > m_sigma_py_b2
Definition: GenEventBeamEffectBooster.h:69
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
beamspotman.dir
string dir
Definition: beamspotman.py:623
Simulation::GenEventBeamEffectBooster::boostParticle
void boostParticle(HepMC::GenParticlePtr &p, const CLHEP::HepLorentzRotation &transform) const
apply boost to individual GenParticles
Definition: GenEventBeamEffectBooster.cxx:151
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
Simulation::GenEventBeamEffectBooster::GenEventBeamEffectBooster
GenEventBeamEffectBooster(const std::string &t, const std::string &n, const IInterface *p)
Constructor with parameters.
Definition: GenEventBeamEffectBooster.cxx:23
Simulation::GenEventBeamEffectBooster::m_rndGenSvc
ServiceHandle< IAthRNGSvc > m_rndGenSvc
Definition: GenEventBeamEffectBooster.h:59
Simulation::GenEventBeamEffectBooster::finalize
StatusCode finalize() override final
Athena algtool's Hooks.
Definition: GenEventBeamEffectBooster.cxx:47
RNGWrapper.h
Simulation::GenEventBeamEffectBooster::m_pbeam2
Gaudi::Property< double > m_pbeam2
Definition: GenEventBeamEffectBooster.h:77
Simulation::GenEventBeamEffectBooster::m_randomEngineName
Gaudi::Property< std::string > m_randomEngineName
Name of the random number stream.
Definition: GenEventBeamEffectBooster.h:61
egammaEnergyPositionAllSamples::e2
double e2(const xAOD::CaloCluster &cluster)
return the uncorrected cluster energy in 2nd sampling
Simulation::GenEventBeamEffectBooster::m_sigma_px_b2
Gaudi::Property< double > m_sigma_px_b2
Definition: GenEventBeamEffectBooster.h:67
Simulation::GenEventBeamEffectBooster::m_sigma_py_b1
Gaudi::Property< double > m_sigma_py_b1
Definition: GenEventBeamEffectBooster.h:68
Simulation
Definition: BeamEffectsAlg.cxx:21
Simulation::GenEventBeamEffectBooster::m_applyDivergence
Gaudi::Property< bool > m_applyDivergence
Definition: GenEventBeamEffectBooster.h:63
Simulation::GenEventBeamEffectBooster::m_beam2ParticleMass
Gaudi::Property< double > m_beam2ParticleMass
Definition: GenEventBeamEffectBooster.h:79
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
Simulation::GenEventBeamEffectBooster::m_applyBoost
Gaudi::Property< bool > m_applyBoost
Definition: GenEventBeamEffectBooster.h:62
Simulation::GenEventBeamEffectBooster::manipulate
StatusCode manipulate(HepMC::GenEvent &ge, const EventContext &ctx) const override final
modifies the given GenEvent
Definition: GenEventBeamEffectBooster.cxx:139