00001 #include "TrackingTools/PatternTools/interface/TwoTrackMinimumDistanceHelixHelix.h"
00002 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
00003 #include "MagneticField/Engine/interface/MagneticField.h"
00004 #include "TrackingTools/TrajectoryParametrization/interface/GlobalTrajectoryParameters.h"
00005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00006
00007 using namespace std;
00008
00009 namespace {
00010 inline GlobalPoint operator - ( const GlobalPoint & a, const GlobalPoint & b ){
00011 return GlobalPoint ( a.x() - b.x(), a.y() - b.y(), a.z() - b.z() );
00012 }
00013
00014 inline GlobalPoint operator + ( const GlobalPoint & a, const GlobalPoint & b ){
00015 return GlobalPoint ( a.x() + b.x(), a.y() + b.y(), a.z() + b.z() );
00016 }
00017
00018 inline GlobalPoint operator / ( const GlobalPoint & a, const double b ){
00019 return GlobalPoint ( a.x() / b, a.y() / b, a.z() / b );
00020 }
00021
00022 inline GlobalPoint operator * ( const GlobalPoint & a, const double b ){
00023 return GlobalPoint ( a.x() * b, a.y() * b, a.z() * b );
00024 }
00025
00026 inline GlobalPoint operator * ( const double b , const GlobalPoint & a ){
00027 return GlobalPoint ( a.x() * b, a.y() * b, a.z() * b );
00028 }
00029
00030 inline double square ( const double s ) { return s*s; }
00031 }
00032
00033 TwoTrackMinimumDistanceHelixHelix::TwoTrackMinimumDistanceHelixHelix():
00034 theH(), theG(), pointsUpdated(false), themaxjump(20),thesingjac(.1), themaxiter(4)
00035 { }
00036
00037 TwoTrackMinimumDistanceHelixHelix::~TwoTrackMinimumDistanceHelixHelix() {}
00038
00039 bool TwoTrackMinimumDistanceHelixHelix::updateCoeffs(
00040 const GlobalPoint & gpH, const GlobalPoint & gpG )
00041 {
00042
00043 const double Bc2kH = theH->magneticField().inTesla(gpH).z() * 2.99792458e-3;
00044
00045 const double Bc2kG = theG->magneticField().inTesla(gpG).z() * 2.99792458e-3;
00046 const double Hn= theH->momentum().mag();
00047 const double Gn= theG->momentum().mag();
00048 thelambdaH=asin ( theH->momentum().z() / Hn );
00049
00050 if ( Hn == 0. || Gn == 0. )
00051 {
00052 edm::LogWarning ("TwoTrackMinimumDistanceHelixHelix")
00053 << "momentum of input trajectory is zero.";
00054 return true;
00055 };
00056
00057 if ( theH->charge() == 0. || theG->charge() == 0. )
00058 {
00059 edm::LogWarning ("TwoTrackMinimumDistanceHelixHelix")
00060 << "charge of input track is zero.";
00061 return true;
00062 };
00063
00064 if ( Bc2kG == 0. )
00065 {
00066 edm::LogWarning ("TwoTrackMinimumDistanceHelixHelix")
00067 << "magnetic field at point " << gpG << " is zero.";
00068 return true;
00069 };
00070
00071 if ( Bc2kH == 0. )
00072 {
00073 edm::LogWarning ("TwoTrackMinimumDistanceHelixHelix")
00074 << "magnetic field at point " << gpH << " is zero.";
00075 return true;
00076 };
00077
00078 theh= Hn / (theH->charge() * Bc2kH ) *
00079 sqrt( 1 - square ( ( theH->momentum().z() / Hn )));
00080 thesinpH0= - theH->momentum().y() / ( theH->charge() * Bc2kH * theh );
00081 thecospH0= - theH->momentum().x() / ( theH->charge() * Bc2kH * theh );
00082 thetanlambdaH = - theH->momentum().z() / ( theH->charge() * Bc2kH * theh);
00083 thepH0 = atan2 ( thesinpH0 , thecospH0 );
00084 thelambdaG=asin ( theG->momentum().z()/( Gn ) );
00085 theg= Gn / (theG->charge() * Bc2kG ) *
00086 sqrt( 1 - square ( ( theG->momentum().z() / Gn )));
00087 thesinpG0= - theG->momentum().y() / ( theG->charge()* Bc2kG * theg );
00088 thecospG0= - theG->momentum().x() / ( theG->charge() * Bc2kG * theg );
00089 thetanlambdaG = - theG->momentum().z() / ( theG->charge() * Bc2kG * theg);
00090
00091 thepG0 = atan2 ( thesinpG0 , thecospG0 );
00092
00093 thea=theH->position().x() - theG->position().x() + theg * thesinpG0 -
00094 theh * thesinpH0;
00095 theb=theH->position().y() - theG->position().y() - theg * thecospG0 +
00096 theh * thecospH0;
00097 thec1= theh * thetanlambdaH * thetanlambdaH;
00098 thec2= -theg * thetanlambdaG * thetanlambdaG;
00099 thed1= -theg * thetanlambdaG * thetanlambdaH;
00100 thed2= theh * thetanlambdaG * thetanlambdaH;
00101 thee1= thetanlambdaH * ( theH->position().z() - theG->position().z() -
00102 theh * thepH0 * thetanlambdaH + theg * thepG0 * thetanlambdaG );
00103 thee2= thetanlambdaG * ( theH->position().z() - theG->position().z() -
00104 theh * thepH0 * thetanlambdaH + theg * thepG0 * thetanlambdaG );
00105 return false;
00106 }
00107
00108 bool TwoTrackMinimumDistanceHelixHelix::oneIteration(
00109 double & dH, double & dG ) const
00110 {
00111 thesinpH=sin(thepH);
00112 thecospH=cos(thepH);
00113 thesinpG=sin(thepG);
00114 thecospG=cos(thepG);
00115
00116 const double A11= theh * ( - thesinpH * ( thea - theg * thesinpG ) +
00117 thecospH * ( theb + theg * thecospG ) + thec1);
00118 if (A11 < 0) { return true; };
00119 const double A22= -theg * (- thesinpG * ( thea + theh * thesinpH ) +
00120 thecospG*( theb - theh * thecospH ) + thec2);
00121 if (A22 < 0) { return true; };
00122 const double A12= theh * (-theg * thecospG * thecospH -
00123 theg * thesinpH * thesinpG + thed1);
00124 const double A21= -theg * (theh * thecospG * thecospH +
00125 theh * thesinpH * thesinpG + thed2);
00126 const double deta = A11 * A22 - A12 * A21;
00127 const double z1=theh * ( thecospH * ( thea - theg * thesinpG ) + thesinpH *
00128 ( theb + theg*thecospG ) + thec1 * thepH + thed1 * thepG + thee1);
00129 const double z2=-theg * (thecospG * ( thea + theh * thesinpH ) + thesinpG *
00130 ( theb - theh*thecospH ) + thec2 * thepG + thed2 * thepH + thee2);
00131
00132 dH=( z1 * A22 - z2 * A12 ) / deta;
00133 dG=( z2 * A11 - z1 * A21 ) / deta;
00134 if ( fabs(deta) < thesingjac ) { return true; };
00135
00136 thepH -= dH;
00137 thepG -= dG;
00138 return false;
00139 }
00140
00141 inline bool TwoTrackMinimumDistanceHelixHelix::parallelTracks() const
00142 {
00143 bool retval=false;
00144 if (fabs(theH->momentum().x() - theG->momentum().x()) < .00000001 )
00145 if (fabs(theH->momentum().y() - theG->momentum().y()) < .00000001 )
00146 if (fabs(theH->momentum().z() - theG->momentum().z()) < .00000001 )
00147 if (theH->charge()==theG->charge()) retval=true;
00148 return retval;
00149 }
00150
00151
00152 bool TwoTrackMinimumDistanceHelixHelix::calculate(
00153 const GlobalTrajectoryParameters & G,
00154 const GlobalTrajectoryParameters & H, const float qual )
00155 {
00156 pointsUpdated = false;
00157 theG= (GlobalTrajectoryParameters *) &G;
00158 theH= (GlobalTrajectoryParameters *) &H;
00159 bool retval=false;
00160
00161 if ( updateCoeffs ( theG->position(), theH->position() ) )
00162 {
00163 return true;
00164 };
00165
00166 thepG = thepG0;
00167 thepH = thepH0;
00168
00169 int counter=0;
00170 double pH=0; double pG=0;
00171 do {
00172 retval=oneIteration ( pG, pH );
00173 if ( !finite(pG) || !finite(pH) ) retval=true;
00174 if ( counter++>themaxiter ) retval=true;
00175 } while ( (!retval) && ( fabs(pG) > qual || fabs(pH) > qual ));
00176 if ( fabs ( theg * ( thepG - thepG0 ) ) > themaxjump ) retval=true;
00177 if ( fabs ( theh * ( thepH - thepH0 ) ) > themaxjump ) retval=true;
00178 return retval;
00179 }
00180
00181 double TwoTrackMinimumDistanceHelixHelix::firstAngle() const
00182 {
00183 return thepG;
00184 }
00185
00186 double TwoTrackMinimumDistanceHelixHelix::secondAngle() const
00187 {
00188 return thepH;
00189 }
00190
00191 void TwoTrackMinimumDistanceHelixHelix::finalPoints() const
00192 {
00193 pointG = GlobalPoint (
00194 theG->position().x() + theg * ( sin ( thepG) - thesinpG0) ,
00195 theG->position().y() + theg * ( - cos ( thepG) + thecospG0 ),
00196 theG->position().z() + theg * ( thetanlambdaG * ( thepG- thepG0 ))
00197 );
00198 pathG = ( thepG- thepG0 ) * (theg*sqrt(1+thetanlambdaG*thetanlambdaG)) ;
00199
00200 pointH = GlobalPoint (
00201 theH->position().x() + theh * ( sin ( thepH) - thesinpH0 ),
00202 theH->position().y() + theh * ( - cos ( thepH) + thecospH0 ),
00203 theH->position().z() + theh * ( thetanlambdaH * ( thepH- thepH0 ))
00204 );
00205 pathH = ( thepH- thepH0 ) * (theh*sqrt(1+thetanlambdaH*thetanlambdaH)) ;
00206 pointsUpdated = true;
00207 }
00208
00209 pair <double, double> TwoTrackMinimumDistanceHelixHelix::pathLength() const
00210 {
00211 if (!pointsUpdated)finalPoints();
00212 return pair <double, double> ( pathG, pathH);
00213 }
00214
00215 pair <GlobalPoint, GlobalPoint> TwoTrackMinimumDistanceHelixHelix::points()
00216 const
00217 {
00218 if (!pointsUpdated)finalPoints();
00219 return pair<GlobalPoint, GlobalPoint> (pointG, pointH);
00220 }
00221