CMS 3D CMS Logo

MultipleScattering.cc
Go to the documentation of this file.
7 
8 #include <cmath>
9 #include <memory>
10 
11 #include <Math/AxisAngle.h>
12 
17 
18 
20 // Author: Patrick Janot
21 // Date: 8-Jan-2004
22 //
23 // Revision: Class structure modified to match SimplifiedGeometryPropagator
24 // Fixed a bug in which particles could no longer be on the layer after scattering
25 // S. Kurz, 29 May 2017
27 
28 
30 
31 namespace fastsim
32 {
34 
38  {
39  public:
42 
44  ~MultipleScattering() override{;};
45 
47 
53  void interact(Particle & particle,const SimplifiedGeometry & layer, std::vector<std::unique_ptr<Particle> > & secondaries, const RandomEngineAndDistribution & random) override;
54 
55  private:
57  XYZVector orthogonal(const XYZVector& aVector) const;
58 
59  double minPt_;
60  double radLenInCm_;
61  };
62 }
63 
65  : fastsim::InteractionModel(name)
66 {
67  // Set the minimal pT for interaction
68  minPt_ = cfg.getParameter<double>("minPt");
69  // Material properties
70  radLenInCm_ = cfg.getParameter<double>("radLen");
71 }
72 
73 
74 void fastsim::MultipleScattering::interact(fastsim::Particle & particle, const SimplifiedGeometry & layer, std::vector<std::unique_ptr<fastsim::Particle> > & secondaries, const RandomEngineAndDistribution & random)
75 {
76  //
77  // only charged particles
78  //
79  if(particle.charge()==0)
80  {
81  return;
82  }
83 
84  double radLengths = layer.getThickness(particle.position(),particle.momentum());
85  //
86  // no material
87  //
88  if(radLengths < 1E-10)
89  {
90  return;
91  }
92 
93  // particle must have minimum pT
94  if(particle.momentum().Pt() < minPt_)
95  {
96  return;
97  }
98 
99  double p2 = particle.momentum().Vect().Mag2();
100  double m2 = particle.momentum().mass2();
101  double e = std::sqrt(p2+m2);
102 
103  // This is p*beta
104  double pbeta = p2 / e;
105 
106  // Average multiple scattering angle from Moliere radius
107  // The sqrt(2) factor is because of the *space* angle
108  double theta0 = 0.0136 / pbeta * particle.charge()
109  * std::sqrt(2. * radLengths)
110  * (1. + 0.038 * std::log(radLengths));
111 
112  // Generate multiple scattering space angle perpendicular to the particle motion
113  double theta = random.gaussShoot(0.,theta0);
114  // Plus a random rotation angle around the particle motion
115  double phi = 2. * M_PI * random.flatShoot();
116 
117  // The two rotations
118  ROOT::Math::AxisAngle rotation1(orthogonal(particle.momentum().Vect()), theta);
119  ROOT::Math::AxisAngle rotation2(particle.momentum().Vect(), phi);
120  // Rotate!
121  XYZVector rotated = rotation2((rotation1(particle.momentum().Vect())));
122  particle.momentum().SetXYZT(rotated.X(),
123  rotated.Y(),
124  rotated.Z(),
125  particle.momentum().E());
126 
127  // Generate mutiple scattering displacements in cm (assuming the detectors
128  // are silicon only to determine the thickness) in the directions orthogonal
129  // to the vector normal to the surface
130  double xp = (cos(phi) * theta / 2. + random.gaussShoot(0., theta0) / sqrt(12.))
131  * radLengths * radLenInCm_;
132  double yp = (sin(phi) * theta / 2. + random.gaussShoot(0., theta0) / sqrt(12.))
133  * radLengths * radLenInCm_;
134 
135  // Determine a unitary vector tangent to the surface
136  XYZVector normal;
137  if(layer.isForward()){
138  normal = XYZVector(0., 0., particle.momentum().Pz() > 0. ? 1. : -1.);
139  }
140  else{
141  double norm = particle.position().Rho();
142  normal = XYZVector(particle.position().X() / norm, particle.position().Y() / norm, 0.);
143  }
144  XYZVector tangent = orthogonal(normal);
145  // The total displacement
146  XYZVector delta = xp*tangent + yp*normal.Cross(tangent);
147  // Translate!
148  particle.position().SetXYZT(particle.position().X()+delta.X(),
149  particle.position().Y()+delta.Y(),
150  particle.position().Z()+delta.Z(),
151  particle.position().T());
152 
153  // Make sure particle is still physically on the layer (particle moved on a tangent but a barrel layer is bent)
154  // Happens only in very very few cases
155  if(!layer.isForward() && std::abs(layer.getGeomProperty() - particle.position().Rho()) > 1e-2){
156  // Scale positions so the radii agree
157  double scalePos = layer.getGeomProperty() / particle.position().Rho();
158  particle.position().SetXYZT(
159  particle.position().X() * scalePos,
160  particle.position().Y() * scalePos,
161  particle.position().Z(),
162  particle.position().T());
163 
164  // Add a protection in case something goes wrong
165  if(std::abs(layer.getGeomProperty() - particle.position().Rho()) > 1e-2){
166  throw cms::Exception("fastsim::MultipleScattering") << "particle no longer on layer's surface";
167  }
168  }
169 }
170 
171 XYZVector
173 {
174  double x = fabs(aVector.X());
175  double y = fabs(aVector.Y());
176  double z = fabs(aVector.Z());
177 
178  if(x < y)
179  return x < z ?
180  XYZVector(0.,aVector.Z(),-aVector.Y()) :
181  XYZVector(aVector.Y(),-aVector.X(),0.);
182  else
183  return y < z ?
184  XYZVector(-aVector.Z(),0.,aVector.X()) :
185  XYZVector(aVector.Y(),-aVector.X(),0.);
186 }
187 
188 
192  "fastsim::MultipleScattering"
193  );
dbl * delta
Definition: mlp_gen.cc:36
T getParameter(std::string const &) const
Implementation of a generic detector layer (base class for forward/barrel layers).
const math::XYZTLorentzVector & position() const
Return position of the particle.
Definition: Particle.h:142
double flatShoot(double xmin=0.0, double xmax=1.0) const
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
Geom::Theta< T > theta() const
virtual bool isForward() const =0
Returns false/true depending if the object is a (non-abstract) barrel/forward layer.
TRandom random
Definition: MVATrainer.cc:138
~MultipleScattering() override
Default destructor.
Base class for any interaction model between a particle and a tracker layer.
math::XYZVector XYZVector
XYZVector orthogonal(const XYZVector &aVector) const
Return an orthogonal vector.
T sqrt(T t)
Definition: SSEVec.h:18
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double p2[4]
Definition: TauolaWrapper.h:90
#define M_PI
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
const double getGeomProperty() const
Return geometric attribute of the layer.
double charge() const
Return charge of the particle.
Definition: Particle.h:139
virtual const double getThickness(const math::XYZTLorentzVector &position) const =0
Return thickness of the layer at a given position.
MultipleScattering(const std::string &name, const edm::ParameterSet &cfg)
Constructor.
double radLenInCm_
Radiation length of material (usually silicon X0=9.360)
math::XYZVector XYZVector
double gaussShoot(double mean=0.0, double sigma=1.0) const
Implementation of multiple scattering in the tracker layers.
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
Definition: Particle.h:145
#define DEFINE_EDM_PLUGIN(factory, type, name)
Definition of a generic FastSim Particle which can be propagated through the detector (formerly Parti...
Definition: Particle.h:19
void interact(Particle &particle, const SimplifiedGeometry &layer, std::vector< std::unique_ptr< Particle > > &secondaries, const RandomEngineAndDistribution &random) override
Perform the interaction.
double minPt_
Cut on minimum pT of particle.