CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/TrackingTools/PatternTools/src/ClosestApproachInRPhi.cc

Go to the documentation of this file.
00001 #include "TrackingTools/PatternTools/interface/ClosestApproachInRPhi.h"
00002 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h" 
00003 #include "MagneticField/Engine/interface/MagneticField.h"
00004 #include "FWCore/Utilities/interface/Exception.h"
00005 
00006 using namespace std;
00007 
00008 bool ClosestApproachInRPhi::calculate(const TrajectoryStateOnSurface & sta, 
00009                                       const TrajectoryStateOnSurface & stb) 
00010 {
00011   TrackCharge chargeA = sta.charge(); TrackCharge chargeB = stb.charge();
00012   GlobalVector momentumA = sta.globalMomentum();
00013   GlobalVector momentumB = stb.globalMomentum();
00014   GlobalPoint positionA = sta.globalPosition();
00015   GlobalPoint positionB = stb.globalPosition();
00016   paramA = sta.globalParameters();
00017   paramB = stb.globalParameters();
00018   // compute magnetic field ONCE 
00019   bz = sta.freeState()->parameters().magneticField().inTesla(positionA).z() * 2.99792458e-3;
00020 
00021   return compute(chargeA, momentumA, positionA, chargeB, momentumB, positionB);
00022 
00023 }
00024 
00025 
00026 bool ClosestApproachInRPhi::calculate(const FreeTrajectoryState & sta, 
00027                                       const FreeTrajectoryState & stb)
00028 {
00029   TrackCharge chargeA = sta.charge(); TrackCharge chargeB = stb.charge();
00030   GlobalVector momentumA = sta.momentum();
00031   GlobalVector momentumB = stb.momentum();
00032   GlobalPoint positionA = sta.position();
00033   GlobalPoint positionB = stb.position();
00034   paramA = sta.parameters();
00035   paramB = stb.parameters();
00036   // compute magnetic field ONCE 
00037   bz = sta.parameters().magneticField().inTesla(positionA).z() * 2.99792458e-3;
00038 
00039   return compute(chargeA, momentumA, positionA, chargeB, momentumB, positionB);
00040 
00041 }
00042 
00043 pair<GlobalPoint, GlobalPoint> ClosestApproachInRPhi::points() const
00044 {
00045   if (!status_)
00046     throw cms::Exception("TrackingTools/PatternTools","ClosestApproachInRPhi::could not compute track crossing. Check status before calling this method!");
00047   return  pair<GlobalPoint, GlobalPoint> (posA, posB);
00048 }
00049 
00050 
00051 GlobalPoint 
00052 ClosestApproachInRPhi::crossingPoint() const
00053 {
00054   if (!status_)
00055     throw cms::Exception("TrackingTools/PatternTools","ClosestApproachInRPhi::could not compute track crossing. Check status before calling this method!");
00056   return  GlobalPoint(0.5*(posA.basicVector() + posB.basicVector()));
00057                      
00058 }
00059 
00060 
00061 float ClosestApproachInRPhi::distance() const
00062 {
00063   if (!status_)
00064     throw cms::Exception("TrackingTools/PatternTools","ClosestApproachInRPhi::could not compute track crossing. Check status before calling this method!");
00065   return (posB - posA).mag();
00066 }
00067 
00068 
00069 bool ClosestApproachInRPhi::compute(const TrackCharge & chargeA, 
00070                                     const GlobalVector & momentumA, 
00071                                     const GlobalPoint & positionA, 
00072                                     const TrackCharge & chargeB, 
00073                                     const GlobalVector & momentumB, 
00074                                     const GlobalPoint & positionB) 
00075 {
00076 
00077 
00078   // centres and radii of track circles
00079   double xca, yca, ra;
00080   circleParameters(chargeA, momentumA, positionA, xca, yca, ra, bz);
00081   double xcb, ycb, rb;
00082   circleParameters(chargeB, momentumB, positionB, xcb, ycb, rb, bz);
00083 
00084   // points of closest approach in transverse plane
00085   double xg1, yg1, xg2, yg2;
00086   int flag = transverseCoord(xca, yca, ra, xcb, ycb, rb, xg1, yg1, xg2, yg2);
00087   if (flag == 0) {
00088     status_ = false;
00089     return false;
00090   }
00091 
00092   double xga, yga, zga, xgb, ygb, zgb;
00093 
00094   if (flag == 1) {
00095     // two crossing points on each track in transverse plane
00096     // select point for which z-coordinates on the 2 tracks are the closest
00097     double za1 = zCoord(momentumA, positionA, ra, xca, yca, xg1, yg1);
00098     double zb1 = zCoord(momentumB, positionB, rb, xcb, ycb, xg1, yg1);
00099     double za2 = zCoord(momentumA, positionA, ra, xca, yca, xg2, yg2);
00100     double zb2 = zCoord(momentumB, positionB, rb, xcb, ycb, xg2, yg2);
00101 
00102     if (abs(zb1 - za1) < abs(zb2 - za2)) {
00103       xga = xg1; yga = yg1; zga = za1; zgb = zb1;
00104     }
00105     else {
00106       xga = xg2; yga = yg2; zga = za2; zgb = zb2;
00107     }
00108     xgb = xga; ygb = yga;
00109   }
00110   else {
00111     // one point of closest approach on each track in transverse plane
00112     xga = xg1; yga = yg1;
00113     zga = zCoord(momentumA, positionA, ra, xca, yca, xga, yga);
00114     xgb = xg2; ygb = yg2;
00115     zgb = zCoord(momentumB, positionB, rb, xcb, ycb, xgb, ygb);
00116   }
00117 
00118   posA = GlobalPoint(xga, yga, zga);
00119   posB = GlobalPoint(xgb, ygb, zgb);
00120   status_ = true;
00121   return true;
00122 }
00123 
00124 pair <GlobalTrajectoryParameters, GlobalTrajectoryParameters>
00125 ClosestApproachInRPhi::trajectoryParameters () const
00126 {
00127   if (!status_)
00128     throw cms::Exception("TrackingTools/PatternTools","ClosestApproachInRPhi::could not compute track crossing. Check status before calling this method!");
00129   pair <GlobalTrajectoryParameters, GlobalTrajectoryParameters> 
00130     ret ( newTrajectory( posA, paramA, bz),
00131           newTrajectory( posB, paramB, bz) );
00132   return ret;
00133 }
00134 
00135 GlobalTrajectoryParameters 
00136 ClosestApproachInRPhi::newTrajectory( const GlobalPoint & newpt, const GlobalTrajectoryParameters & oldgtp, double bz )
00137 {
00138   // First we need the centers of the circles.
00139   double qob = oldgtp.charge()/bz;
00140   double xc =  oldgtp.position().x() + qob *  oldgtp.momentum().y();
00141   double yc =  oldgtp.position().y() - qob *  oldgtp.momentum().x();
00142 
00143   // and of course....  
00144   double npx = (newpt.y()-yc)*(bz/oldgtp.charge());
00145   double npy = (xc-newpt.x())*(bz/oldgtp.charge());
00146  
00147   /*
00148    * old code: slow and wrong
00149    *
00150   // now we do a translation, move the center of circle to (0,0,0).
00151   double dx1 = oldgtp.position().x() - xc;
00152   double dy1 = oldgtp.position().y() - yc;
00153   double dx2 = newpt.x() - xc;
00154   double dy2 = newpt.y() - yc;
00155  
00156   // now for the angles:
00157   double cosphi = ( dx1 * dx2 + dy1 * dy2 ) / 
00158     ( sqrt ( dx1 * dx1 + dy1 * dy1 ) * sqrt ( dx2 * dx2 + dy2 * dy2 ));
00159   double sinphi = - oldgtp.charge() * sqrt ( 1 - cosphi * cosphi );
00160   
00161   // Finally, the new momenta:
00162   double px = cosphi * oldgtp.momentum().x() - sinphi * oldgtp.momentum().y();
00163   double py = sinphi * oldgtp.momentum().x() + cosphi * oldgtp.momentum().y();
00164   
00165   std::cout << px-npx << " " << py-npy << ", " << oldgtp.charge() << std::endl;
00166   */
00167 
00168   GlobalVector vta ( npx, npy, oldgtp.momentum().z() );
00169   GlobalTrajectoryParameters gta( newpt , vta , oldgtp.charge(), &(oldgtp.magneticField()) );
00170   return gta;
00171 }
00172 
00173 void 
00174 ClosestApproachInRPhi::circleParameters(const TrackCharge& charge, 
00175                                         const GlobalVector& momentum, 
00176                                         const GlobalPoint& position, 
00177                                         double& xc, double& yc, double& r,
00178                                         double bz)
00179 {
00180 
00181   // compute radius of circle
00185 //   double bz = MagneticField::inInverseGeV(position).z();
00186 
00187   // signed_r directed towards circle center, along F_Lorentz = q*v X B
00188   double qob = charge/bz;
00189   double signed_r = qob*momentum.transverse();
00190   r = abs(signed_r);
00194   // compute centre of circle
00195   // double phi = momentum.phi();
00196   // xc = signed_r*sin(phi) + position.x();
00197   // yc = -signed_r*cos(phi) + position.y();
00198   xc =  position.x() + qob * momentum.y();
00199   yc =  position.y() - qob * momentum.x();
00200 
00201 }
00202 
00203 
00204 int 
00205 ClosestApproachInRPhi::transverseCoord(double cxa, double cya, double ra, 
00206                                        double cxb, double cyb, double rb, 
00207                                        double & xg1, double & yg1, 
00208                                        double & xg2, double & yg2)
00209 {
00210   int flag = 0;
00211   double x1, y1, x2, y2;
00212 
00213   // new reference frame with origin in (cxa, cya) and x-axis 
00214   // directed from (cxa, cya) to (cxb, cyb)
00215 
00216   double d_ab = sqrt((cxb - cxa)*(cxb - cxa) + (cyb - cya)*(cyb - cya));
00217   if (d_ab == 0) { // concentric circles
00218     return 0;
00219   }
00220   // elements of rotation matrix
00221   double u = (cxb - cxa) / d_ab;
00222   double v = (cyb - cya) / d_ab;
00223 
00224   // conditions for circle intersection
00225   if (d_ab <= ra + rb && d_ab >= abs(rb - ra)) {
00226 
00227     // circles cross each other
00228     flag = 1;
00229 
00230     // triangle (ra, rb, d_ab)
00231     double cosphi = (ra*ra - rb*rb + d_ab*d_ab) / (2*ra*d_ab);
00232     double sinphi2 = 1. - cosphi*cosphi;
00233     if (sinphi2 < 0.) { sinphi2 = 0.; cosphi = 1.; }
00234 
00235     // intersection points in new frame
00236     double sinphi = sqrt(sinphi2);
00237     x1 = ra*cosphi; y1 = ra*sinphi; x2 = x1; y2 = -y1;
00238   } 
00239   else if (d_ab > ra + rb) {
00240 
00241     // circles are external to each other
00242     flag = 2;
00243 
00244     // points of closest approach in new frame 
00245     // are on line between 2 centers
00246     x1 = ra; y1 = 0; x2 = d_ab - rb; y2 = 0;
00247   }
00248   else if (d_ab < abs(rb - ra)) {
00249 
00250     // circles are inside each other
00251     flag = 2;
00252 
00253     // points of closest approach in new frame are on line between 2 centers
00254     // choose 2 closest points
00255     double sign = 1.;
00256     if (ra <= rb) sign = -1.;
00257     x1 = sign*ra; y1 = 0; x2 = d_ab + sign*rb; y2 = 0;
00258   }
00259   else {
00260     return 0;
00261   }
00262 
00263   // intersection points in global frame, transverse plane
00264   xg1 = u*x1 - v*y1 + cxa; yg1 = v*x1 + u*y1 + cya;
00265   xg2 = u*x2 - v*y2 + cxa; yg2 = v*x2 + u*y2 + cya;
00266 
00267   return flag;
00268 }
00269 
00270 
00271 double 
00272 ClosestApproachInRPhi::zCoord(const GlobalVector& mom, 
00273                               const GlobalPoint& pos, 
00274                               double r, double xc, double yc, 
00275                               double xg, double yg)
00276 {
00277 
00278   // starting point
00279   double x = pos.x(); double y = pos.y(); double z = pos.z();
00280 
00281   double px = mom.x(); double py = mom.y(); double pz = mom.z();
00282 
00283   // rotation angle phi from starting point to crossing point (absolute value)
00284   // -- compute sin(phi/2) if phi smaller than pi/4, 
00285   // -- cos(phi) if phi larger than pi/4
00286   double phi = 0.;
00287   double sinHalfPhi = sqrt((x-xg)*(x-xg) + (y-yg)*(y-yg))/(2*r);
00288   if (sinHalfPhi < 0.383) { // sin(pi/8)
00289     phi = 2*asin(sinHalfPhi);
00290   }
00291   else {
00292     double cosPhi = ((x-xc)*(xg-xc) + (y-yc)*(yg-yc))/(r*r);
00293     if (std::abs(cosPhi) > 1) cosPhi = (cosPhi > 0 ? 1 : -1);
00294     phi = abs(acos(cosPhi));
00295   }
00296   // -- sign of phi
00297   double signPhi = ((x - xc)*(yg - yc) - (xg - xc)*(y - yc) > 0) ? 1. : -1.;
00298 
00299   // sign of track angular momentum
00300   // if rotation is along angular momentum, delta z is along pz
00301   double signOmega = ((x - xc)*py - (y - yc)*px > 0) ? 1. : -1.;
00302 
00303   // delta z
00304   // -- |dz| = |cos(theta) * path along helix|
00305   //         = |cos(theta) * arc length along circle / sin(theta)|
00306   double dz = signPhi*signOmega*(pz/mom.transverse())*phi*r;
00307 
00308   return z + dz;
00309 }