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 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
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
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
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
00096
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
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
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
00144 double npx = (newpt.y()-yc)*(bz/oldgtp.charge());
00145 double npy = (xc-newpt.x())*(bz/oldgtp.charge());
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
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
00185
00186
00187
00188 double qob = charge/bz;
00189 double signed_r = qob*momentum.transverse();
00190 r = abs(signed_r);
00194
00195
00196
00197
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
00214
00215
00216 double d_ab = sqrt((cxb - cxa)*(cxb - cxa) + (cyb - cya)*(cyb - cya));
00217 if (d_ab == 0) {
00218 return 0;
00219 }
00220
00221 double u = (cxb - cxa) / d_ab;
00222 double v = (cyb - cya) / d_ab;
00223
00224
00225 if (d_ab <= ra + rb && d_ab >= abs(rb - ra)) {
00226
00227
00228 flag = 1;
00229
00230
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
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
00242 flag = 2;
00243
00244
00245
00246 x1 = ra; y1 = 0; x2 = d_ab - rb; y2 = 0;
00247 }
00248 else if (d_ab < abs(rb - ra)) {
00249
00250
00251 flag = 2;
00252
00253
00254
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
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
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
00284
00285
00286 double phi = 0.;
00287 double sinHalfPhi = sqrt((x-xg)*(x-xg) + (y-yg)*(y-yg))/(2*r);
00288 if (sinHalfPhi < 0.383) {
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
00297 double signPhi = ((x - xc)*(yg - yc) - (xg - xc)*(y - yc) > 0) ? 1. : -1.;
00298
00299
00300
00301 double signOmega = ((x - xc)*py - (y - yc)*px > 0) ? 1. : -1.;
00302
00303
00304
00305
00306 double dz = signPhi*signOmega*(pz/mom.transverse())*phi*r;
00307
00308 return z + dz;
00309 }