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
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
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
00093
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
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
00136 double xc, yc, r;
00137 circleParameters( oldgtp.charge(), oldgtp.momentum(),
00138 oldgtp.position(), xc, yc, r, oldgtp.magneticField() );
00139
00140
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
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
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
00173
00174 double bz = magField.inTesla(position).z() * 2.99792458e-3;
00175
00176
00177 double signed_r = charge*momentum.transverse() / bz;
00178 r = abs(signed_r);
00182
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
00200
00201
00202 double d_ab = sqrt((cxb - cxa)*(cxb - cxa) + (cyb - cya)*(cyb - cya));
00203 if (d_ab == 0) {
00204 return 0;
00205 }
00206
00207 double u = (cxb - cxa) / d_ab;
00208 double v = (cyb - cya) / d_ab;
00209
00210
00211 if (d_ab <= ra + rb && d_ab >= abs(rb - ra)) {
00212
00213
00214 flag = 1;
00215
00216
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
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
00228 flag = 2;
00229
00230
00231
00232 x1 = ra; y1 = 0; x2 = d_ab - rb; y2 = 0;
00233 }
00234 else if (d_ab < abs(rb - ra)) {
00235
00236
00237 flag = 2;
00238
00239
00240
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
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
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
00270
00271
00272 double phi = 0.;
00273 double sinHalfPhi = sqrt((x-xg)*(x-xg) + (y-yg)*(y-yg))/(2*r);
00274 if (sinHalfPhi < 0.383) {
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
00282 double signPhi = ((x - xc)*(yg - yc) - (xg - xc)*(y - yc) > 0) ? 1. : -1.;
00283
00284
00285
00286 double signOmega = ((x - xc)*py - (y - yc)*px > 0) ? 1. : -1.;
00287
00288
00289
00290
00291 double dz = signPhi*signOmega*(pz/mom.transverse())*phi*r;
00292
00293 return z + dz;
00294 }