CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:48:25 2009 for CMSSW by  doxygen 1.5.4