CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:44:51 2009 for CMSSW by  doxygen 1.5.4