Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-06-26 07:05:37

0001 /**
0002  \file
0003  Implementation of class Smear::RadialTracker.
0004  
0005  \author    Will Foreman
0006  \date      2011-08-19
0007  \copyright 2011 Brookhaven National Lab
0008  */
0009 
0010 #include "eicsmear/smear/RadialTracker.h"
0011 
0012 #include <algorithm>
0013 #include <cmath>
0014 #include <limits>
0015 #include <list>
0016 
0017 #include <TMath.h>
0018 
0019 namespace {
0020 
0021 // Functor for testing non-existent intersection points,
0022 struct NoIntersection {
0023   bool operator()(const TVector3& v) const {
0024     return TMath::IsNaN(v.z());
0025   }
0026 };
0027 
0028 }  // anonymous namespace
0029 
0030 namespace Smear {
0031 
0032 RadialTracker::RadialTracker()
0033 : Tracker(2., 0.03, 0.001)
0034 , mNFitPoints(25.)
0035 , mInnerRadius(0.1)
0036 , mOuterRadius(1.)
0037 , mZMin(-1.5)
0038 , mZMax(1.5) {
0039 }
0040 
0041 RadialTracker::RadialTracker(double inner, double outer,
0042                              double zmin, double zmax,
0043                              double Bb, double nrl,
0044                              double sigmaRPhi, double N)
0045 : Tracker(Bb, nrl, sigmaRPhi)
0046 , mNFitPoints(N)
0047 , mInnerRadius(inner)
0048 , mOuterRadius(outer)
0049 // Require zmin < zmax
0050 , mZMin(std::min(zmin, zmax))
0051 , mZMax(std::max(zmin, zmax)) {
0052 }
0053 
0054 RadialTracker::~RadialTracker() {
0055 }
0056 
0057 void RadialTracker::Print(Option_t* /* option */) const {
0058   std::cout << ClassName() << " with:" << std::endl <<
0059   "\tinner radius " << mInnerRadius << " m\n" <<
0060   "\touter radius " << mOuterRadius << " m\n" <<
0061   "\tlength " << mZMin << " to " << mZMax <<
0062   " (= " << mZMax - mZMin << ") m\n" <<
0063   "\tmagnetic field " << mMagField << " Tesla\n" <<
0064   "\t" << mNRadLengths << " radiation lengths\n" <<
0065   "\tpoint resolution " << mSigmaRPhi * 1.e6 << " microns\n" <<
0066   "\t" << mNFitPoints << " fit points" << std::endl;
0067 }
0068 
0069 TVector3 RadialTracker::ComputeIntersectionWithRadius(
0070     const erhic::VirtualParticle& p, double radius) const {
0071   // Compute the longitudinal position at which the intersection occurs.
0072   // Adjust for any z offset in the vertex of the particle.
0073   const double z = radius / tan(p.GetTheta()) + p.GetVertex().z();
0074   TVector3 intersection(0., 0., std::numeric_limits<double>::quiet_NaN());
0075   if (z > mZMin && z < mZMax) {
0076     // Don't care about phi angle, so set x and y arbitrarily.
0077     intersection.SetXYZ(radius, 0., z);
0078   }  // if
0079   return intersection;
0080 }
0081 
0082 TVector3 RadialTracker::ComputeIntersectionWithPlane(
0083     const erhic::VirtualParticle& p, double z) const {
0084   // Compute the radius of intersection, adusting for any z offset
0085   // in the particle vertex.
0086   const double r = (z - p.GetVertex().z()) * tan(p.GetTheta());
0087   TVector3 intersection(0., 0., std::numeric_limits<double>::quiet_NaN());
0088   if (r > mInnerRadius && r < mOuterRadius) {
0089     // Don't care about phi angle, so set x and y arbitrarily.
0090     intersection.SetXYZ(r, 0., z);
0091   }  // if
0092   return intersection;
0093 }
0094 
0095 TVector3 RadialTracker::ComputePath(const erhic::VirtualParticle& p) const {
0096   // There are 4 valid ways for the particle to intersect the cylinder.
0097   // It can intersect:
0098   // 1) nothing
0099   // 2) both faces
0100   // 3) both radii
0101   // 4) one face and one radius
0102   // Finding anything else indicates an error - if it
0103   // enters the (finite) volume, it must exit it.
0104   // So, first compute all 4 possible intersection points
0105   std::list<TVector3> xyz;
0106   xyz.push_back(ComputeIntersectionWithRadius(p, mInnerRadius));
0107   xyz.push_back(ComputeIntersectionWithRadius(p, mOuterRadius));
0108   xyz.push_back(ComputeIntersectionWithPlane(p, mZMin));
0109   xyz.push_back(ComputeIntersectionWithPlane(p, mZMax));
0110   // Remove those where there was no intersection
0111   xyz.erase(std::remove_if(xyz.begin(), xyz.end(), NoIntersection()),
0112             xyz.end());
0113   // We should have either exactly 2 intersection points, or none, in
0114   // which case the particle missed the detector and we return zero.
0115   // Anything else indicates an error, so return zero path length for
0116   // those also.
0117   TVector3 path(0., 0., 0.);
0118   if (2 == xyz.size()) {
0119     // Arrange the points so that the path vector is going outward
0120     // from the origin
0121     if (xyz.front().Mag() > xyz.back().Mag()) {
0122       path = xyz.front() - xyz.back();
0123     } else {
0124       path = xyz.back() - xyz.front();
0125     }  // if
0126   }  // if
0127   return path;
0128 }
0129 
0130 double RadialTracker::L(const erhic::VirtualParticle& p) const {
0131   double Length = ComputePath(p).Mag();
0132   return Length;
0133 }
0134 
0135 double RadialTracker::LPrime(const erhic::VirtualParticle& p) const {
0136   return ComputePath(p).Perp();
0137 }
0138 
0139 int RadialTracker::NPoints(const erhic::VirtualParticle& p) const {
0140   int n;
0141   float n_float;
0142   if (LPrime(p) == (mOuterRadius - mInnerRadius)) {
0143     n = mNFitPoints;
0144   } else {
0145     n_float = mNFitPoints * ComputePath(p).Perp() /
0146               (mOuterRadius - mInnerRadius);
0147     n = floor(n_float + 0.5);
0148   }  // if
0149   return n;
0150 }
0151 
0152 bool RadialTracker::Accepts(const erhic::VirtualParticle& p) const {
0153   // Require the transverse path length to exceed half of the
0154   // radial width per fit point, otherwise the detector essentially
0155   // doesn't "see" the particle.
0156   if (NPoints(p) > 2) {
0157     return true;
0158   }  // if
0159   return false;
0160 }
0161 
0162 double RadialTracker::GetThetaMin() const {
0163   if (mZMax > 0.) {
0164     return atan2(mInnerRadius, mZMax);
0165   } else {
0166     return atan2(mOuterRadius, mZMax);
0167   }  // if
0168 }
0169 
0170 double RadialTracker::GetThetaMax() const {
0171   if (mZMin > 0.) {
0172     return atan2(mOuterRadius, mZMin);
0173   } else {
0174     return atan2(mInnerRadius, mZMin);
0175   }  // if
0176 }
0177 
0178 }  // namespace Smear