EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RadialTracker.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RadialTracker.cxx
1 
11 
12 #include <algorithm>
13 #include <cmath>
14 #include <limits>
15 #include <list>
16 
17 #include <TMath.h>
18 
19 namespace {
20 
21 // Functor for testing non-existent intersection points,
22 struct NoIntersection {
23  bool operator()(const TVector3& v) const {
24  return TMath::IsNaN(v.z());
25  }
26 };
27 
28 } // anonymous namespace
29 
30 namespace Smear {
31 
33 : Tracker(2., 0.03, 0.001)
34 , mNFitPoints(25.)
35 , mInnerRadius(0.1)
36 , mOuterRadius(1.)
37 , mZMin(-1.5)
38 , mZMax(1.5) {
39 }
40 
41 RadialTracker::RadialTracker(double inner, double outer,
42  double zmin, double zmax,
43  double Bb, double nrl,
44  double sigmaRPhi, double N)
45 : Tracker(Bb, nrl, sigmaRPhi)
46 , mNFitPoints(N)
47 , mInnerRadius(inner)
48 , mOuterRadius(outer)
49 // Require zmin < zmax
50 , mZMin(std::min(zmin, zmax))
51 , mZMax(std::max(zmin, zmax)) {
52 }
53 
55 }
56 
57 void RadialTracker::Print(Option_t* /* option */) const {
58  std::cout << ClassName() << " with:" << std::endl <<
59  "\tinner radius " << mInnerRadius << " m\n" <<
60  "\touter radius " << mOuterRadius << " m\n" <<
61  "\tlength " << mZMin << " to " << mZMax <<
62  " (= " << mZMax - mZMin << ") m\n" <<
63  "\tmagnetic field " << mMagField << " Tesla\n" <<
64  "\t" << mNRadLengths << " radiation lengths\n" <<
65  "\tpoint resolution " << mSigmaRPhi * 1.e6 << " microns\n" <<
66  "\t" << mNFitPoints << " fit points" << std::endl;
67 }
68 
70  const erhic::VirtualParticle& p, double radius) const {
71  // Compute the longitudinal position at which the intersection occurs.
72  // Adjust for any z offset in the vertex of the particle.
73  const double z = radius / tan(p.GetTheta()) + p.GetVertex().z();
74  TVector3 intersection(0., 0., std::numeric_limits<double>::quiet_NaN());
75  if (z > mZMin && z < mZMax) {
76  // Don't care about phi angle, so set x and y arbitrarily.
77  intersection.SetXYZ(radius, 0., z);
78  } // if
79  return intersection;
80 }
81 
83  const erhic::VirtualParticle& p, double z) const {
84  // Compute the radius of intersection, adusting for any z offset
85  // in the particle vertex.
86  const double r = (z - p.GetVertex().z()) * tan(p.GetTheta());
87  TVector3 intersection(0., 0., std::numeric_limits<double>::quiet_NaN());
88  if (r > mInnerRadius && r < mOuterRadius) {
89  // Don't care about phi angle, so set x and y arbitrarily.
90  intersection.SetXYZ(r, 0., z);
91  } // if
92  return intersection;
93 }
94 
96  // There are 4 valid ways for the particle to intersect the cylinder.
97  // It can intersect:
98  // 1) nothing
99  // 2) both faces
100  // 3) both radii
101  // 4) one face and one radius
102  // Finding anything else indicates an error - if it
103  // enters the (finite) volume, it must exit it.
104  // So, first compute all 4 possible intersection points
105  std::list<TVector3> xyz;
106  xyz.push_back(ComputeIntersectionWithRadius(p, mInnerRadius));
107  xyz.push_back(ComputeIntersectionWithRadius(p, mOuterRadius));
108  xyz.push_back(ComputeIntersectionWithPlane(p, mZMin));
109  xyz.push_back(ComputeIntersectionWithPlane(p, mZMax));
110  // Remove those where there was no intersection
111  xyz.erase(std::remove_if(xyz.begin(), xyz.end(), NoIntersection()),
112  xyz.end());
113  // We should have either exactly 2 intersection points, or none, in
114  // which case the particle missed the detector and we return zero.
115  // Anything else indicates an error, so return zero path length for
116  // those also.
117  TVector3 path(0., 0., 0.);
118  if (2 == xyz.size()) {
119  // Arrange the points so that the path vector is going outward
120  // from the origin
121  if (xyz.front().Mag() > xyz.back().Mag()) {
122  path = xyz.front() - xyz.back();
123  } else {
124  path = xyz.back() - xyz.front();
125  } // if
126  } // if
127  return path;
128 }
129 
131  double Length = ComputePath(p).Mag();
132  return Length;
133 }
134 
136  return ComputePath(p).Perp();
137 }
138 
140  int n;
141  float n_float;
142  if (LPrime(p) == (mOuterRadius - mInnerRadius)) {
143  n = mNFitPoints;
144  } else {
145  n_float = mNFitPoints * ComputePath(p).Perp() /
147  n = floor(n_float + 0.5);
148  } // if
149  return n;
150 }
151 
153  // Require the transverse path length to exceed half of the
154  // radial width per fit point, otherwise the detector essentially
155  // doesn't "see" the particle.
156  if (NPoints(p) > 2) {
157  return true;
158  } // if
159  return false;
160 }
161 
163  if (mZMax > 0.) {
164  return atan2(mInnerRadius, mZMax);
165  } else {
166  return atan2(mOuterRadius, mZMax);
167  } // if
168 }
169 
171  if (mZMin > 0.) {
172  return atan2(mOuterRadius, mZMin);
173  } else {
174  return atan2(mInnerRadius, mZMin);
175  } // if
176 }
177 
178 } // namespace Smear