CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/RecoPixelVertexing/PixelLowPtUtilities/src/ThirdHitPrediction.cc

Go to the documentation of this file.
00001 #include "RecoPixelVertexing/PixelLowPtUtilities/interface/ThirdHitPrediction.h"
00002 
00003 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00004 
00005 #include "TrackingTools/DetLayers/interface/BarrelDetLayer.h"
00006 #include "TrackingTools/DetLayers/interface/ForwardDetLayer.h"
00007 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00008 
00009 #include "RecoTracker/TkMSParametrization/interface/MultipleScatteringParametrisation.h"
00010 #include "RecoPixelVertexing/PixelTrackFitting/src/CircleFromThreePoints.h"
00011 
00012 #include "MagneticField/Engine/interface/MagneticField.h"
00013 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00014 
00015 #include "TrackingTools/TransientTrackingRecHit/interface/TransientTrackingRecHitBuilder.h"
00016 #include "TrackingTools/Records/interface/TransientRecHitRecord.h"
00017 
00018 inline float sqr(float x) { return x*x; }
00019 
00020 using namespace std;
00021 
00022 /*****************************************************************************/
00023 ThirdHitPrediction::ThirdHitPrediction
00024   (const TrackingRegion & region, GlobalPoint inner, GlobalPoint outer,
00025    const edm::EventSetup& es,
00026    double nSigMultipleScattering, double maxAngleRatio,
00027    string builderName)
00028 {
00029  using namespace edm;
00030  ESHandle<MagneticField> magfield;
00031  es.get<IdealMagneticFieldRecord>().get(magfield);
00032 
00033  edm::ESHandle<TransientTrackingRecHitBuilder> ttrhbESH;
00034  es.get<TransientRecHitRecord>().get(builderName,ttrhbESH);
00035  theTTRecHitBuilder = ttrhbESH.product();
00036 
00037  Bz = fabs(magfield->inInverseGeV(GlobalPoint(0,0,0)).z());
00038 
00039  c0 = Global2DVector(region.origin().x(),
00040                      region.origin().y());
00041 
00042  r0 = region.originRBound();
00043  rm = region.ptMin() / Bz;
00044 
00045  g1 = inner;
00046  g2 = outer;
00047 
00048  p1 = Global2DVector(g1.x(), g1.y());
00049  p2 = Global2DVector(g2.x(), g2.y());
00050 
00051  dif = p1 - p2;
00052 
00053  // Prepare circles of minimal pt (rm) and cylinder of origin (r0)
00054  keep = true;
00055  arc_0m = findArcIntersection(findMinimalCircles (rm),
00056                               findTouchingCircles(r0), keep);
00057 
00058  nSigma   = nSigMultipleScattering;
00059  maxRatio = maxAngleRatio;
00060 }
00061 
00062 /*****************************************************************************/
00063 ThirdHitPrediction::~ThirdHitPrediction()
00064 {
00065 }
00066 
00067 /*****************************************************************************/
00068 void ThirdHitPrediction::invertCircle(Global2DVector& c,float& r)
00069 {
00070   float s = dif.mag2() / ((c - p1).mag2() - sqr(r));
00071 
00072   c = p1 + (c - p1)*s;
00073   r *= fabsf(s);
00074 }
00075 
00076 /*****************************************************************************/
00077 void ThirdHitPrediction::invertPoint(Global2DVector& p)
00078 {
00079   float s = dif.mag2() / (p - p1).mag2();
00080 
00081   p = p1 + (p - p1)*s;
00082 }
00083 
00084 /*****************************************************************************/
00085 pair<float,float> ThirdHitPrediction::findMinimalCircles(float r)
00086 { 
00087   pair<float,float> a(0.,0.);
00088 
00089   if(dif.mag2() <  2 * sqr(r))
00090     a = pair<float,float>( dif.phi(),
00091                            0.5*acos(1 - 0.5 * dif.mag2()/sqr(r)) );
00092 
00093   return a;
00094 }
00095 
00096 /*****************************************************************************/
00097 pair<float,float> ThirdHitPrediction::findTouchingCircles(float r)
00098 {
00099   Global2DVector c = c0;
00100   invertCircle(c,r);
00101 
00102   pair<float,float> a(0.,0.);
00103   a = pair<float,float>( (c - p2).phi(),
00104                           0.5*acos(1 - 2*sqr(r)/(c - p2).mag2()) );
00105 
00106   return a;
00107 }
00108 
00109 /*****************************************************************************/
00110 pair<float,float> ThirdHitPrediction::findArcIntersection
00111   (pair<float,float> a, pair<float,float> b, bool& keep)
00112 { 
00113   // spin closer
00114   while(b.first < a.first - M_PI) b.first += 2*M_PI;
00115   while(b.first > a.first + M_PI) b.first -= 2*M_PI;
00116 
00117   float min,max;
00118 
00119   if(a.first - a.second > b.first - b.second)
00120     min = a.first - a.second;
00121   else
00122   { min = b.first - b.second; keep = false; }
00123 
00124   if(a.first + a.second < b.first + b.second)
00125     max = a.first + a.second;
00126   else
00127   { max = b.first + b.second; keep = false; }
00128   
00129   pair<float,float> c(0.,0.);
00130 
00131   if(min < max)
00132   {
00133     c.first  = 0.5*(max + min);
00134     c.second = 0.5*(max - min);
00135   }
00136 
00137   return c;
00138 }
00139 
00140 /*****************************************************************************/
00141 void ThirdHitPrediction::fitParabola
00142   (const float x[3], const float y[3], float par[3])
00143 { 
00144   float s2 = sqr(x[0]) * (y[1] - y[2]) +
00145              sqr(x[1]) * (y[2] - y[0]) +
00146              sqr(x[2]) * (y[0] - y[1]);
00147   
00148   float s1 =     x[0]  * (y[1] - y[2]) +
00149                  x[1]  * (y[2] - y[0]) +
00150                  x[2]  * (y[0] - y[1]);
00151 
00152   float s3 = (x[0] - x[1]) * (x[1] - x[2]) * (x[2] - x[0]);
00153   float s4 = x[0]*x[1]*y[2] * (x[0] - x[1]) +
00154              x[0]*y[1]*x[2] * (x[2] - x[0]) +
00155              y[0]*x[1]*x[2] * (x[1] - x[2]);
00156 
00157   par[2] =  s1 / s3; // a2
00158   par[1] = -s2 / s3; // a1
00159   par[0] = -s4 / s3; // a0
00160 }
00161 
00162 /*****************************************************************************/
00163 void ThirdHitPrediction::findRectangle
00164   (const float x[3], const float y[3], const float par[3],
00165    float phi[2],float z[2])
00166 { 
00167   // Initial guess
00168   phi[0] = min(x[0],x[2]); z[0] = min(y[0],y[2]);
00169   phi[1] = max(x[0],x[2]); z[1] = max(y[0],y[2]);
00170 
00171   // Extremum: position and value
00172   float xe = -par[1]/(2*par[2]);
00173   float ye = par[0] - sqr(par[1])/(4*par[2]);
00174 
00175   // Check if extremum is inside the phi range
00176   if(phi[0] < xe  && xe < phi[1])
00177   {
00178     if(ye < z[0]) z[0] = ye;
00179     if(ye > z[1]) z[1] = ye;
00180   }
00181 }
00182 
00183 /*****************************************************************************/
00184 float ThirdHitPrediction::areaParallelogram
00185   (const Global2DVector& a, const Global2DVector& b)
00186 {
00187   return a.x() * b.y() - a.y() * b.x();
00188 }
00189 
00190 /*****************************************************************************/
00191 float ThirdHitPrediction::angleRatio
00192   (const Global2DVector& p3, const Global2DVector& c)
00193 {
00194   float rad2 = (p1 - c).mag2();
00195 
00196   float a12 = asin(fabsf(areaParallelogram(p1 - c, p2 - c)) / rad2);
00197   float a23 = asin(fabsf(areaParallelogram(p2 - c, p3 - c)) / rad2);
00198 
00199   return a23/a12;
00200 }
00201 
00202 /*****************************************************************************/
00203 void ThirdHitPrediction::spinCloser(float phi[3])
00204 {
00205   while(phi[1] < phi[0] - M_PI) phi[1] += 2*M_PI;
00206   while(phi[1] > phi[0] + M_PI) phi[1] -= 2*M_PI;
00207 
00208   while(phi[2] < phi[1] - M_PI) phi[2] += 2*M_PI;
00209   while(phi[2] > phi[1] + M_PI) phi[2] -= 2*M_PI;
00210 }
00211 
00212 /*****************************************************************************/
00213 void ThirdHitPrediction::calculateRangesBarrel
00214   (float r3, float phi[2],float z[2], bool keep)
00215 {
00216   pair<float,float> arc_all =
00217     findArcIntersection(arc_0m, findTouchingCircles(r3), keep);
00218 
00219   if(arc_all.second != 0.)
00220   {
00221     Global2DVector c3(0.,0.); // barrel at r3
00222     invertCircle(c3,r3);      // inverted
00223 
00224     float angle[3];           // prepare angles
00225     angle[0] = arc_all.first - arc_all.second;
00226     angle[1] = arc_all.first;
00227     angle[2] = arc_all.first + arc_all.second;
00228 
00229     float phi3[3], z3[3];
00230     Global2DVector delta = c3 - p2;
00231 
00232     for(int i=0; i<3; i++)
00233     {
00234       Global2DVector vec(cos(angle[i]), sin(angle[i])); // unit vector
00235       float lambda = delta*vec - sqrt(sqr(delta*vec) - delta*delta + sqr(r3));
00236 
00237       Global2DVector p3 = p2 + lambda * vec;  // inverted third hit 
00238       invertPoint(p3);                        // third hit
00239       phi3[i] = p3.phi();                     // phi of third hit
00240 
00241       float ratio;
00242 
00243       if(keep && i==1)
00244       { // Straight line
00245         ratio = (p2 - p3).mag() / (p1 - p2).mag();
00246       }
00247       else
00248       { // Circle
00249         Global2DVector c = p2 - vec * (vec * (p2 - p1)); // inverted antipodal
00250         invertPoint(c);                                  // antipodal
00251         c = 0.5*(p1 + c);                                // center
00252 
00253         ratio = angleRatio(p3,c);
00254       }
00255 
00256       z3[i] = g2.z() + (g2.z() - g1.z()) * ratio;        // z of third hit
00257     }
00258 
00259     spinCloser(phi3);
00260 
00261     // Parabola on phi - z
00262     float par[3];
00263     fitParabola  (phi3,z3, par);
00264     findRectangle(phi3,z3, par, phi,z);
00265   }
00266 }
00267 
00268 /*****************************************************************************/
00269 void ThirdHitPrediction::calculateRangesForward
00270   (float z3, float phi[2],float r[2], bool keep)
00271 {
00272   float angle[3];           // prepare angles
00273   angle[0] = arc_0m.first - arc_0m.second;
00274   angle[1] = arc_0m.first;
00275   angle[2] = arc_0m.first + arc_0m.second;
00276 
00277   float ratio = (z3 - g2.z()) / (g2.z() - g1.z());
00278 
00279   if(0 < ratio  && ratio < maxRatio)
00280   {
00281     float phi3[3], r3[3];
00282 
00283     for(int i=0; i<3; i++)
00284     {
00285       Global2DVector p3;
00286 
00287       if(keep && i==1)
00288       { // Straight line
00289         p3 = p2 + ratio * (p2 - p1);
00290       }
00291       else
00292       { // Circle
00293         Global2DVector vec(cos(angle[i]), sin(angle[i])); // unit vector
00294   
00295         Global2DVector c = p2 - vec * (vec * (p2 - p1));  // inverted antipodal
00296         invertPoint(c);                                   // antipodal
00297         c = 0.5*(p1 + c);                                 // center
00298 
00299         float rad2 = (p1 - c).mag2();
00300 
00301         float a12 = asin(areaParallelogram(p1 - c, p2 - c) / rad2);
00302         float a23 = ratio * a12;
00303 
00304         p3 = c + Global2DVector((p2-c).x()*cos(a23) - (p2-c).y()*sin(a23),
00305                                 (p2-c).x()*sin(a23) + (p2-c).y()*cos(a23));
00306       }
00307 
00308       phi3[i] = p3.phi();
00309       r3[i]   = p3.mag();
00310     }
00311 
00312     spinCloser(phi3);
00313 
00314     // Parabola on phi - z
00315     float par[3];
00316     fitParabola  (phi3,r3, par);
00317     findRectangle(phi3,r3, par, phi,r);
00318   }
00319 }
00320 
00321 /*****************************************************************************/
00322 void ThirdHitPrediction::calculateRanges
00323   (float rz3, float phi[2],float rz[2])
00324 {
00325   // Clear
00326   phi[0] = 0.; rz[0] = 0.;
00327   phi[1] = 0.; rz[1] = 0.;
00328 
00329   // Calculate
00330   if(theBarrel) calculateRangesBarrel (rz3, phi,rz, keep);
00331            else calculateRangesForward(rz3, phi,rz, keep);
00332 }
00333 
00334 /*****************************************************************************/
00335 void ThirdHitPrediction::getRanges
00336   (const DetLayer *layer, float phi[],float rz[])
00337 {
00338   theLayer = layer;
00339   
00340   if (layer) initLayer(layer);
00341 
00342   float phi_inner[2],rz_inner[2];
00343   calculateRanges(theDetRange.min(), phi_inner,rz_inner);
00344 
00345   float phi_outer[2],rz_outer[2];
00346   calculateRanges(theDetRange.max(), phi_outer,rz_outer);
00347 
00348   if( (phi_inner[0] == 0. && phi_inner[1] == 0.) ||
00349       (phi_outer[0] == 0. && phi_outer[1] == 0.) )
00350   {
00351     phi[0] = 0.;
00352     phi[1] = 0.;
00353 
00354      rz[0] = 0.;
00355      rz[1] = 0.;
00356   }
00357   else
00358   {
00359     while(phi_outer[0] > phi_inner[0] + M_PI)
00360     { phi_outer[0] -= 2*M_PI; phi_outer[1] -= 2*M_PI; }
00361 
00362     while(phi_outer[0] < phi_inner[0] - M_PI)
00363     { phi_outer[0] += 2*M_PI; phi_outer[1] += 2*M_PI; }
00364 
00365     phi[0] = min(phi_inner[0],phi_outer[0]);
00366     phi[1] = max(phi_inner[1],phi_outer[1]);
00367   
00368      rz[0] = min( rz_inner[0], rz_outer[0]);
00369      rz[1] = max( rz_inner[1], rz_outer[1]);
00370   }
00371 }
00372 
00373 /*****************************************************************************/
00374 void ThirdHitPrediction::getRanges
00375   (float rz3, float phi[],float rz[])
00376 {
00377   calculateRanges(rz3, phi,rz);
00378 }
00379 
00380 /*****************************************************************************/
00381 bool ThirdHitPrediction::isCompatibleWithMultipleScattering
00382   (GlobalPoint g3, vector<const TrackingRecHit*> h,
00383    vector<GlobalVector>& globalDirs, const edm::EventSetup& es)
00384 {
00385   Global2DVector p1(g1.x(),g1.y());
00386   Global2DVector p2(g2.x(),g2.y());
00387   Global2DVector p3(g3.x(),g3.y());
00388 
00389   CircleFromThreePoints circle(g1,g2,g3);
00390 
00391   if(circle.curvature() != 0.)
00392   {
00393   Global2DVector c (circle.center().x(), circle.center().y());
00394 
00395   float rad2 = (p1 - c).mag2();
00396   float a12 = asin(fabsf(areaParallelogram(p1 - c, p2 - c)) / rad2);
00397   float a23 = asin(fabsf(areaParallelogram(p2 - c, p3 - c)) / rad2);
00398 
00399   float slope = (g2.z() - g1.z()) / a12;
00400 
00401   float rz3 = g2.z() + slope * a23;
00402   float delta_z = g3.z() - rz3;
00403 
00404   // Transform to tt
00405   vector<TransientTrackingRecHit::RecHitPointer> th;
00406   for(vector<const TrackingRecHit*>::iterator ih = h.begin(); ih!= h.end(); ih++)
00407     th.push_back(theTTRecHitBuilder->build(*ih));
00408 
00409   float sigma1_le2 = max(th[0]->parametersError()[0][0],
00410                          th[0]->parametersError()[1][1]);
00411   float sigma2_le2 = max(th[1]->parametersError()[0][0],
00412                          th[1]->parametersError()[1][1]);
00413 
00414   float sigma_z2 = (1 + a23/a12)*(1 + a23/a12) * sigma2_le2 +
00415                    (    a23/a12)*(    a23/a12) * sigma1_le2;
00416 
00417   float cotTheta = slope * circle.curvature(); // == sinhEta
00418   float coshEta  = sqrt(1 + sqr(cotTheta));    // == 1/sinTheta
00419 
00420   float pt = Bz / circle.curvature();
00421   float p  = pt * coshEta;
00422 
00423   float m_pi = 0.13957018;
00424   float beta = p / sqrt(sqr(p) + sqr(m_pi));
00425 
00426   MultipleScatteringParametrisation msp(theLayer,es);
00427   PixelRecoPointRZ rz2(g2.perp(), g2.z());
00428 
00429   float sigma_z = msp(pt, cotTheta, rz2) / beta;
00430 
00431   // Calculate globalDirs
00432   float sinTheta =       1. / coshEta;
00433   float cosTheta = cotTheta * sinTheta;
00434 
00435   int dir;
00436   if(areaParallelogram(p1 - c, p2 - c) > 0) dir = 1; else dir = -1;
00437 
00438   float curvature = circle.curvature();
00439 
00440   {
00441    Global2DVector v = (p1 - c)*curvature*dir;
00442    globalDirs.push_back(GlobalVector(-v.y()*sinTheta,v.x()*sinTheta,cosTheta));
00443   }
00444 
00445   {
00446    Global2DVector v = (p2 - c)*curvature*dir;
00447    globalDirs.push_back(GlobalVector(-v.y()*sinTheta,v.x()*sinTheta,cosTheta));
00448   }
00449 
00450   {
00451    Global2DVector v = (p3 - c)*curvature*dir;
00452    globalDirs.push_back(GlobalVector(-v.y()*sinTheta,v.x()*sinTheta,cosTheta));
00453   }
00454 
00455   // Multiple scattering
00456   float sigma_ms  = sigma_z * coshEta;
00457 
00458   // Local error squared
00459   float sigma_le2 = max(th[2]->parametersError()[0][0],
00460                         th[2]->parametersError()[1][1]);
00461 
00462   return (delta_z*delta_z / (sigma_ms*sigma_ms + sigma_le2 + sigma_z2)
00463           < nSigma * nSigma);
00464   }
00465 
00466   return false;
00467 }
00468 
00469 /*****************************************************************************/
00470 void ThirdHitPrediction::initLayer(const DetLayer *layer)
00471 {
00472   if ( layer->location() == GeomDetEnumerators::barrel) {
00473     theBarrel = true;
00474     theForward = false;
00475     const BarrelDetLayer& bl = dynamic_cast<const BarrelDetLayer&>(*layer);
00476     float halfThickness  = bl.surface().bounds().thickness()/2;
00477     float radius = bl.specificSurface().radius();
00478     theDetRange = Range(radius-halfThickness, radius+halfThickness);
00479   } else if ( layer->location() == GeomDetEnumerators::endcap) {
00480     theBarrel= false;
00481     theForward = true;
00482     const ForwardDetLayer& fl = dynamic_cast<const ForwardDetLayer&>(*layer);
00483     float halfThickness  = fl.surface().bounds().thickness()/2;
00484     float zLayer = fl.position().z() ;
00485     theDetRange = Range(zLayer-halfThickness, zLayer+halfThickness);
00486   }
00487 }