CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoEgamma/EgammaPhotonAlgos/src/TangentApproachInRPhi.cc

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