Go to the documentation of this file.00001 #include "TrackingTools/PatternTools/interface/TwoTrackMinimumDistanceHelixLine.h"
00002 #include "TrackingTools/TrajectoryParametrization/interface/GlobalTrajectoryParameters.h"
00003 #include "MagneticField/Engine/interface/MagneticField.h"
00004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00005 #include <iostream>
00006 #include <iomanip>
00007
00008 using namespace std;
00009
00010 bool TwoTrackMinimumDistanceHelixLine::updateCoeffs()
00011 {
00012 bool isFirstALine = firstGTP->charge() == 0. || firstGTP->magneticField().inTesla(firstGTP->position()).z() == 0.;
00013 bool isSecondALine = secondGTP->charge() == 0. || secondGTP->magneticField().inTesla(secondGTP->position()).z() == 0.;
00014 if (isFirstALine && !isSecondALine ) {
00015 theL= firstGTP;
00016 theH= secondGTP;
00017 } else if (!isFirstALine && isSecondALine) {
00018 theH= firstGTP;
00019 theL= secondGTP;
00020 } else {
00021 edm::LogWarning ("TwoTrackMinimumDistanceHelixLine")
00022 << "Error in track charge: "
00023 << "One of the tracks has to be charged, and the other not." << endl
00024 << "Track Charges: "<<firstGTP->charge() << " and " <<secondGTP->charge();
00025 return true;
00026 }
00027
00028 Hn = theH->momentum().mag();
00029 Ln = theL->momentum().mag();
00030
00031 if ( Hn == 0. || Ln == 0. )
00032 {
00033 edm::LogWarning ("TwoTrackMinimumDistanceHelixLine")
00034 << "Momentum of input trajectory is zero.";
00035 return true;
00036 };
00037
00038 GlobalPoint lOrig = theL->position();
00039 GlobalPoint hOrig = theH->position();
00040 posDiff = GlobalVector((lOrig - hOrig).basicVector());
00041 X = posDiff.x();
00042 Y = posDiff.y();
00043 Z = posDiff.z();
00044 theLp = theL->momentum();
00045 px = theLp.x(); px2 = px*px;
00046 py = theLp.y(); py2 = py*py;
00047 pz = theLp.z(); pz2 = pz*pz;
00048
00049 const double Bc2kH = theH->magneticField().inTesla(hOrig).z() * 2.99792458e-3;
00050
00051
00052 if ( Bc2kH == 0. )
00053 {
00054 edm::LogWarning ("TwoTrackMinimumDistanceHelixLine")
00055 << "Magnetic field at point " << hOrig << " is zero.";
00056 return true;
00057 };
00058
00059 theh= - Hn / (theH->charge() * Bc2kH ) *
00060 sqrt( 1 - ( ( (theH->momentum().z()*theH->momentum().z()) / (Hn*Hn) )));
00061
00062 thetanlambdaH = - theH->momentum().z() / ( theH->charge() * Bc2kH * theh);
00063
00064 thePhiH0 = theH->momentum().phi();
00065 thesinPhiH0= sin(thePhiH0);
00066 thecosPhiH0= cos(thePhiH0);
00067
00068 aa = (X + theh*thesinPhiH0)*(py2 + pz2) - px*(py*Y + pz*Z);
00069 bb = (Y - theh*thecosPhiH0)*(px2 + pz2) - py*(px*X + pz*Z);
00070 cc = pz*theh*thetanlambdaH;
00071 dd = theh* px *py;
00072 ee = theh*(px2 - py2);
00073 ff = (px2 + py2)*theh*thetanlambdaH*thetanlambdaH;
00074
00075 baseFct = thetanlambdaH * (Z*(px2+py2) - pz*(px*X + py*Y));
00076 baseDer = - ff;
00077 return false;
00078 }
00079
00080 bool TwoTrackMinimumDistanceHelixLine::oneIteration(
00081 double & thePhiH, double & fct, double & derivative ) const
00082 {
00083
00084 double thesinPhiH = sin(thePhiH);
00085 double thecosPhiH = cos(thePhiH);
00086
00087
00088
00089 fct = baseFct;
00090 fct -= ff*(thePhiH - thePhiH0);
00091 fct += thecosPhiH * aa;
00092 fct += thesinPhiH * bb;
00093 fct += cc*(thePhiH - thePhiH0)*(px * thecosPhiH + py * thesinPhiH);
00094 fct += cc * (px * (thesinPhiH - thesinPhiH0) - py * (thecosPhiH - thecosPhiH0));
00095 fct += dd * (thesinPhiH* (thesinPhiH - thesinPhiH0) -
00096 thecosPhiH*(thecosPhiH - thecosPhiH0));
00097 fct += ee * thecosPhiH * thesinPhiH;
00098
00099
00100
00101 derivative = baseDer;
00102 derivative += - thesinPhiH * aa;
00103 derivative += thecosPhiH * bb;
00104 derivative += cc*(thePhiH - thePhiH0)*(py * thecosPhiH - px * thesinPhiH);
00105 derivative += 2* cc*(px * thecosPhiH + py * thesinPhiH);
00106 derivative += dd *(4 * thecosPhiH * thesinPhiH - thecosPhiH * thesinPhiH0 -
00107 thesinPhiH * thecosPhiH0);
00108 derivative += ee * (thecosPhiH*thecosPhiH-thesinPhiH*thesinPhiH);
00109
00110 return false;
00111 }
00112
00113 bool TwoTrackMinimumDistanceHelixLine::calculate(
00114 const GlobalTrajectoryParameters & theFirstGTP,
00115 const GlobalTrajectoryParameters & theSecondGTP, const float qual )
00116 {
00117 pointsUpdated = false;
00118 firstGTP = (GlobalTrajectoryParameters *) &theFirstGTP;
00119 secondGTP = (GlobalTrajectoryParameters *) &theSecondGTP;
00120
00121 if ( updateCoeffs () )
00122 {
00123 return true;
00124 };
00125
00126 double fctVal, derVal, dPhiH;
00127 thePhiH = thePhiH0;
00128
00129 double x1=thePhiH0-M_PI, x2=thePhiH0+M_PI;
00130 for (int j=1; j<=themaxiter; ++j) {
00131 oneIteration(thePhiH, fctVal, derVal);
00132 dPhiH=fctVal/derVal;
00133 thePhiH -= dPhiH;
00134 if ((x1-thePhiH)*(thePhiH-x2) < 0.0) {
00135 LogDebug ("TwoTrackMinimumDistanceHelixLine")
00136 << "Jumped out of brackets in root finding. Will be moved closer.";
00137 thePhiH += (dPhiH*0.8);
00138 }
00139 if (fabs(dPhiH) < qual) {return false;}
00140 }
00141 LogDebug ("TwoTrackMinimumDistanceHelixLine")
00142 <<"Number of steps exceeded. Has not converged.";
00143 return true;
00144 }
00145
00146 double TwoTrackMinimumDistanceHelixLine::firstAngle() const
00147 {
00148 if (firstGTP==theL) return theL->momentum().phi();
00149 else return thePhiH;
00150 }
00151
00152 double TwoTrackMinimumDistanceHelixLine::secondAngle() const
00153 {
00154 if (secondGTP==theL) return theL->momentum().phi();
00155 else return thePhiH;
00156 }
00157
00158 pair <GlobalPoint, GlobalPoint> TwoTrackMinimumDistanceHelixLine::points()
00159 const
00160 {
00161 if (!pointsUpdated)finalPoints();
00162 if (firstGTP==theL)
00163 return pair<GlobalPoint, GlobalPoint> (linePoint, helixPoint);
00164 else return pair<GlobalPoint, GlobalPoint> (helixPoint, linePoint);
00165 }
00166
00167 pair <double, double> TwoTrackMinimumDistanceHelixLine::pathLength() const
00168 {
00169 if (!pointsUpdated)finalPoints();
00170 if (firstGTP==theL)
00171 return pair<double, double> (linePath, helixPath);
00172 else return pair<double, double> (helixPath, linePath);
00173 }
00174
00175 void TwoTrackMinimumDistanceHelixLine::finalPoints() const
00176 {
00177 helixPoint = GlobalPoint (
00178 theH->position().x() + theh * ( sin ( thePhiH) - thesinPhiH0 ),
00179 theH->position().y() + theh * ( - cos ( thePhiH) + thecosPhiH0 ),
00180 theH->position().z() + theh * ( thetanlambdaH * ( thePhiH- thePhiH0 ))
00181 );
00182 helixPath = ( thePhiH- thePhiH0 ) * (theh*sqrt(1+thetanlambdaH*thetanlambdaH)) ;
00183
00184 GlobalVector diff((theL->position() -helixPoint).basicVector());
00185 tL = ( - diff.dot(theLp)) / (Ln*Ln);
00186 linePoint = GlobalPoint (
00187 theL->position().x() + tL * px,
00188 theL->position().y() + tL * py,
00189 theL->position().z() + tL * pz );
00190 linePath = tL * theLp.mag();
00191 pointsUpdated = true;
00192 }