EICInteractionVertexSmear.cxx
Go to the documentation of this file.
1 #include "DDG4/Factories.h"
2 
3 // Framework include files
4 #include "DD4hep/Printout.h"
5 #include "DD4hep/InstanceCount.h"
6 #include "DDG4/Geant4Random.h"
7 #include "DDG4/Geant4Context.h"
8 #include "DDG4/Geant4InputHandling.h"
10 
11 // C/C++ include files
12 #include <cmath>
13 
14 #include "Math/Vector3D.h"
15 #include "Math/Vector4D.h"
16 #include "Math/LorentzRotation.h"
17 #include "Math/AxisAngle.h"
18 #include "Math/Rotation3D.h"
19 #include "Math/RotationX.h"
20 #include "Math/RotationY.h"
21 #include "Math/Boost.h"
22 #include "Math/BoostX.h"
23 #include "Math/BoostX.h"
24 #include "Math/PxPyPzM4D.h"
25 
26 namespace npdet::sim {
27 
28 using namespace dd4hep::sim;
29 
31 EICInteractionVertexSmear::EICInteractionVertexSmear(Geant4Context* ctxt, const std::string& nam)
32  : Geant4GeneratorAction(ctxt, nam)
33 {
35  declareProperty("Offset", m_offset);
36  declareProperty("Sigma_ion", m_sigma_Ion);
37  declareProperty("Sigma_e", m_sigma_Electron);
38  declareProperty("Mask", m_mask = 0);
39  m_needsControl = true;
40 }
41 
44 
47  using namespace ROOT::Math;
48  Geant4Random& rndm = context()->event().random();
49  if (inter) {
50  double dx = rndm.gauss(m_offset.x(), m_sigma_Ion.x());
51  double dy = rndm.gauss(m_offset.y(), m_sigma_Ion.y());
52  double dz = rndm.gauss(m_offset.z(), m_sigma_Ion.z());
53  double dt = rndm.gauss(m_offset.t(), m_sigma_Ion.t());
54  double dxe = rndm.gauss(m_offset.x(), m_sigma_Electron.x());
55  double dye = rndm.gauss(m_offset.y(), m_sigma_Electron.y());
56  double dze = rndm.gauss(m_offset.z(), m_sigma_Electron.z());
57  double dte = rndm.gauss(m_offset.t(), m_sigma_Electron.t());
58  XYZVector ion_dir(0, 0, 1.0);
59  RotationY rotx(-dx);
60  RotationX roty(dy);
61  auto new_ion_dir = rotx(roty(ion_dir));
62 
63  Geant4PrimaryEvent::Interaction::VertexMap::iterator iv;
64  Geant4PrimaryEvent::Interaction::ParticleMap::iterator ip;
65 
66  double alpha = new_ion_dir.Theta();
67  auto rotation_axis = ion_dir.Cross(new_ion_dir).Unit();
68 
69  if (inter->locked) {
70  this->abortRun("Locked interactions may not be boosted!",
71  "Cannot boost interactions with a native G4 primary record!");
72  } else if (alpha != 0.0) {
73 
74  double tanalpha = std::tan(alpha/2.0);
75  double gamma = std::sqrt(1 + tanalpha * tanalpha);
76  double betagamma = tanalpha;
77  double beta = betagamma / gamma;
78 
79  Polar3D boost_vec(beta, M_PI / 2.0, new_ion_dir.Phi());
80 
81  std::cout << " beta = " << beta << "\n";
82 
83  Boost bst(boost_vec);
84  LorentzRotation roty(AxisAngle(rotation_axis, alpha / 2.0));
85 
86  // Now move begin and end-vertex of all primary vertices accordingly
87  for (iv = inter->vertices.begin(); iv != inter->vertices.end(); ++iv) {
88  for (Geant4Vertex* v : (*iv).second) {
89  XYZTVector v0(v->x, v->y, v->z, v->time);
90  auto v1 = roty(bst * v0);
91  v->x = v1.x();
92  v->y = v1.y();
93  v->z = v1.z();
94  v->time = v1.t();
95  }
96  }
97  // Now move begin and end-vertex of all primary and generator particles accordingly
98  for (ip = inter->particles.begin(); ip != inter->particles.end(); ++ip) {
99  Geant4ParticleHandle p = (*ip).second;
100  XYZTVector v0{p->vsx, p->vsy, p->vsz, p->time};
101  auto v1 = roty(bst * v0);
102 
103  PxPyPzMVector p0{p->psx, p->psy, p->psz, p->mass};
104  auto p1 = roty(bst * p0);
105 
106  p->vsx = v1.x();
107  p->vsy = v1.y();
108  p->vsz = v1.z();
109  p->time = v1.t();
110 
111  p->psx = p1.x();
112  p->psy = p1.y();
113  p->psz = p1.z();
114  }
115  }
116 
117  // smearInteraction(this,inter,dx,dy,dz,dt);
118  return;
119  } else {
120  //print("+++ Smearing primary vertex for interaction type %d (%d Vertices, %d particles) "
121  // "by (%+.2e mm, %+.2e mm, %+.2e mm, %+.2e ns)",
122  // m_mask, int(inter->vertices.size()), int(inter->particles.size()), dx, dy, dz, dt);
123  print("+++ No interaction of type %d present.", m_mask);
124  }
125 }
126 
129  typedef std::vector<Geant4PrimaryInteraction*> _I;
130  Geant4PrimaryEvent* evt = context()->event().extension<Geant4PrimaryEvent>();
131 
132  if ( m_mask >= 0 ) {
133  Interaction* inter = evt->get(m_mask);
134  smear(inter);
135  return;
136  }
137  _I interactions = evt->interactions();
138  for(_I::iterator i=interactions.begin(); i != interactions.end(); ++i)
139  smear(*i);
140 }
141 }
142 
143 namespace dd4hep::sim {
145 }
146 DECLARE_GEANT4ACTION(EICInteractionVertexSmear)
147 
void smear(Interaction *interaction) const
Action routine to smear one single interaction according to the properties.
Smear the beam to account for the IP beam divergence.
npdet::sim::EICInteractionVertexSmear EICInteractionVertexSmear
int m_mask
Property: Unique identifier of the interaction created.
detail::increment< T > increment(T &target)
makes function object that increments using operator ++
Definition: clipp.h:1119
void print(OStream &os, const parsing_result &result)
prints parsing result
Definition: clipp.h:6161
EICInteractionVertexSmear()=delete
Inhibit default constructor.
virtual ~EICInteractionVertexSmear()
Default destructor.
virtual void operator()(G4Event *event)
Callback to generate primary particles.
ROOT::Math::PxPyPzEVector m_offset
Property: The constant smearing offset.
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
Geant4PrimaryInteraction Interaction
Interaction definition.
detail::decrement< T > decrement(T &target)
makes function object that increments by a fixed amount using operator +=
Definition: clipp.h:1141
ROOT::Math::PxPyPzEVector m_sigma_Ion
Property: sigma_x,y in units of angle.