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
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
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
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
00140 double xc, yc, r;
00141 circleParameters( oldgtp.charge(), oldgtp.momentum(),
00142 oldgtp.position(), xc, yc, r, oldgtp.magneticField() );
00143
00144
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
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
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
00177
00178 double bz = magField.inTesla(position).z() * 2.99792458e-3;
00179
00180
00181 double signed_r = charge*momentum.transverse() / bz;
00182 r = abs(signed_r);
00186
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
00204
00205
00206 double d_ab = sqrt((cxb - cxa)*(cxb - cxa) + (cyb - cya)*(cyb - cya));
00207 if (d_ab == 0) {
00208 return 0;
00209 }
00210
00211 double u = (cxb - cxa) / d_ab;
00212 double v = (cyb - cya) / d_ab;
00213
00214
00215 if (d_ab <= ra + rb && d_ab >= abs(rb - ra)) {
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 flag = 1;
00231
00232
00233
00234 x1 = ra; y1 = 0; x2 = d_ab - rb; y2 = 0;
00235
00236
00237 }
00238 else if (d_ab > ra + rb) {
00239
00240
00241 flag = 2;
00242
00243
00244
00245 x1 = ra; y1 = 0; x2 = d_ab - rb; y2 = 0;
00246 }
00247 else if (d_ab < abs(rb - ra)) {
00248
00249
00250 flag = 2;
00251
00252
00253
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
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
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
00283
00284
00285 double phi = 0.;
00286 double sinHalfPhi = sqrt((x-xg)*(x-xg) + (y-yg)*(y-yg))/(2*r);
00287 if (sinHalfPhi < 0.383) {
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
00296 double signPhi = ((x - xc)*(yg - yc) - (xg - xc)*(y - yc) > 0) ? 1. : -1.;
00297
00298
00299
00300 double signOmega = ((x - xc)*py - (y - yc)*px > 0) ? 1. : -1.;
00301
00302
00303
00304
00305 double dz = signPhi*signOmega*(pz/mom.transverse())*phi*r;
00306
00307 return z + dz;
00308 }