00001 #include "RecoMuon/TrackerSeedGenerator/interface/L1MuonPixelTrackFitter.h"
00002
00003 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTCand.h"
00004
00005 #include "RecoTracker/TkMSParametrization/interface/PixelRecoLineRZ.h"
00006 #include "RecoTracker/TkMSParametrization/interface/PixelRecoUtilities.h"
00007 #include "RecoPixelVertexing/PixelTrackFitting/src/PixelTrackBuilder.h"
00008 #include "DataFormats/GeometryCommonDetAlgo/interface/Measurement1D.h"
00009 #include "MagneticField/Engine/interface/MagneticField.h"
00010 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00011
00012 #include <math.h>
00013
00014 template <class T> T sqr( T t) {return t*t;}
00015
00016 L1MuonPixelTrackFitter::L1MuonPixelTrackFitter(const edm::ParameterSet& cfg)
00017 : theConfig(cfg)
00018 { }
00019
00020 void L1MuonPixelTrackFitter::setL1Constraint(const L1MuGMTCand & muon)
00021 {
00022 thePhiL1 = muon.phiValue()+0.021817;
00023 theEtaL1 = muon.etaValue();
00024 theChargeL1 = muon.charge();
00025 }
00026
00027 void L1MuonPixelTrackFitter::setPxConstraint(const std::vector<ctfseeding::SeedingHit> & hits)
00028 {
00029 float r1 = hits[0].r();
00030 float r2 = hits[1].r();
00031 float phi1 = hits[0].phi();
00032 float phi2 = hits[1].phi();
00033 theHit1 = GlobalPoint(r1*cos(phi1), r1*sin(phi1), hits[0].z());
00034 theHit2 = GlobalPoint(r2*cos(phi2), r2*sin(phi2), hits[1].z());
00035 }
00036
00037 reco::Track* L1MuonPixelTrackFitter::run( const edm::EventSetup& es,
00038 const std::vector<const TrackingRecHit *>& hits, const TrackingRegion& region) const
00039 {
00040 edm::ESHandle<MagneticField> fieldESH;
00041 es.get<IdealMagneticFieldRecord>().get(fieldESH);
00042
00043 double phi_vtx_fromHits = (theHit2-theHit1).phi();
00044
00045 double invPt = valInversePt(phi_vtx_fromHits, thePhiL1, theEtaL1);
00046 double invPtErr = errInversePt(invPt, theEtaL1);
00047
00048 int charge = (invPt > 0.) ? 1 : -1;
00049 double curvature = PixelRecoUtilities::curvature(invPt, es);
00050
00051 Circle circle(theHit1, theHit2, curvature);
00052
00053 double valPhi = this->valPhi(circle, charge);
00054 double valTip = this->valTip(circle, curvature);
00055 double valZip = this->valZip(curvature, theHit1,theHit2);
00056 double valCotTheta = this->valCotTheta(PixelRecoLineRZ(theHit1,theHit2));
00057
00058 static double invPtErrorScale = theConfig.getParameter<double>("invPtErrorScale");
00059 static double phiErrorScale= theConfig.getParameter<double>("phiErrorScale");
00060 static double cotThetaErrorScale = theConfig.getParameter<double>("cotThetaErrorScale");
00061 static double tipErrorScale = theConfig.getParameter<double>("tipErrorScale");
00062 static double zipErrorScale = theConfig.getParameter<double>("zipErrorScale");
00063
00064
00065
00066 PixelTrackBuilder builder;
00067 double valPt = (fabs(invPt) > 1.e-4) ? 1./fabs(invPt) : 1.e4;
00068 double errPt = invPtErrorScale*invPtErr * valPt*valPt;
00069 double eta = asinh(valCotTheta);
00070 double errPhi = this->errPhi(invPt, eta) * phiErrorScale;
00071 double errCotTheta = this->errCotTheta(invPt, eta) * cotThetaErrorScale;
00072 double errTip = this->errTip(invPt, eta) * tipErrorScale;
00073 double errZip = this->errZip(invPt, eta) * zipErrorScale;
00074
00075 Measurement1D pt(valPt, errPt);
00076 Measurement1D phi(valPhi, errPhi);
00077 Measurement1D cotTheta(valCotTheta, errCotTheta);
00078 Measurement1D tip(valTip, errTip);
00079 Measurement1D zip(valZip, errZip);
00080
00081 float chi2 = 0.;
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 return builder.build(pt, phi, cotTheta, tip, zip, chi2, charge, hits, fieldESH.product());
00097 }
00098
00099
00100 double L1MuonPixelTrackFitter::valPhi(const Circle &circle, int charge) const
00101 {
00102 Circle::Point zero(0.,0.,0.);
00103 Circle::Vector center = circle.center()-zero;
00104 long double radius = center.perp();
00105 center /= radius;
00106 Circle::Vector dir = center.cross(-charge*Circle::Vector(0.,0.,1.));
00107 return dir.phi();
00108 }
00109
00110 double L1MuonPixelTrackFitter::errPhi(double invPt, double eta) const {
00111
00112
00113
00114 double p0,p1;
00115 int ieta = int (10*fabs(eta));
00116 switch (ieta) {
00117 case 0: { p0 = 0.000597506; p1 = 0.00221057; break; }
00118 case 1: { p0 = 0.000591867; p1 = 0.00278744; break; }
00119 case 2: { p0 = 0.000635666; p1 = 0.00207433; break; }
00120 case 3: { p0 = 0.000619086; p1 = 0.00255121; break; }
00121 case 4: { p0 = 0.000572067; p1 = 0.00310618; break; }
00122 case 5: { p0 = 0.000596239; p1 = 0.00288442; break; }
00123 case 6: { p0 = 0.000607608; p1 = 0.00282996; break; }
00124 case 7: { p0 = 0.000606446; p1 = 0.00281118; break; }
00125 case 8: { p0 = 0.000594076; p1 = 0.00280546; break; }
00126 case 9: { p0 = 0.000579615; p1 = 0.00335534; break; }
00127 case 10: { p0 = 0.000659546; p1 = 0.00340443; break; }
00128 case 11: { p0 = 0.000659031; p1 = 0.00343151; break; }
00129 case 12: { p0 = 0.000738391; p1 = 0.00337297; break; }
00130 case 13: { p0 = 0.000798966; p1 = 0.00330008; break; }
00131 case 14: { p0 = 0.000702997; p1 = 0.00562643; break; }
00132 case 15: { p0 = 0.000973417; p1 = 0.00312666; break; }
00133 case 16: { p0 = 0.000995213; p1 = 0.00564278; break; }
00134 case 17: { p0 = 0.00121436; p1 = 0.00572704; break; }
00135 case 18: { p0 = 0.00119216; p1 = 0.00760204; break; }
00136 case 19: { p0 = 0.00141204; p1 = 0.0093777; break; }
00137 default: { p0 = 0.00153161; p1 = 0.00940265; break; }
00138 }
00139 return p0+p1*fabs(invPt);
00140 }
00141
00142
00143 double L1MuonPixelTrackFitter::valCotTheta(const PixelRecoLineRZ& line) const
00144 {
00145 return line.cotLine();
00146 }
00147
00148 double L1MuonPixelTrackFitter::errCotTheta(double invPt, double eta) const
00149 {
00150
00151
00152
00153 double p0,p1;
00154 int ieta = int (10*fabs(eta));
00155 switch (ieta) {
00156 case 0: { p0 = 0.00166115; p1 = 5.75533e-05; break; }
00157 case 1: { p0 = 0.00157525; p1 = 0.000707437; break; }
00158 case 2: { p0 = 0.00122246; p1 = 0.000325456; break; }
00159 case 3: { p0 = 0.000852422; p1 = 0.000429216; break; }
00160 case 4: { p0 = 0.000637561; p1 = 0.00122298; break; }
00161 case 5: { p0 = 0.000555766; p1 = 0.00158096; break; }
00162 case 6: { p0 = 0.000641202; p1 = 0.00143339; break; }
00163 case 7: { p0 = 0.000803207; p1 = 0.000648816; break; }
00164 case 8: { p0 = 0.000741394; p1 = 0.0015289; break; }
00165 case 9: { p0 = 0.000652019; p1 = 0.00168873; break; }
00166 case 10: { p0 = 0.000716902; p1 = 0.00257556; break; }
00167 case 11: { p0 = 0.000800409; p1 = 0.00190563; break; }
00168 case 12: { p0 = 0.000808778; p1 = 0.00264139; break; }
00169 case 13: { p0 = 0.000775757; p1 = 0.00318478; break; }
00170 case 14: { p0 = 0.000705781; p1 = 0.00460576; break; }
00171 case 15: { p0 = 0.000580679; p1 = 0.00748248; break; }
00172 case 16: { p0 = 0.000561667; p1 = 0.00767487; break; }
00173 case 17: { p0 = 0.000521626; p1 = 0.0100178; break; }
00174 case 18: { p0 = 0.00064253; p1 = 0.0106062; break; }
00175 case 19: { p0 = 0.000636868; p1 = 0.0140047; break; }
00176 default: { p0 = 0.000682478; p1 = 0.0163569; break; }
00177 }
00178 return p0+p1*fabs(invPt);
00179 }
00180
00181
00182 double L1MuonPixelTrackFitter::valTip(const Circle &circle, double curvature) const
00183 {
00184 Circle::Point zero(0.,0.,0.);
00185 Circle::Vector center = circle.center()-zero;
00186 long double radius = center.perp();
00187 return radius-1./fabs(curvature);
00188 }
00189
00190 double L1MuonPixelTrackFitter::errTip(double invPt, double eta) const {
00191
00192
00193
00194 double p0,p1;
00195 int ieta = int (10*fabs(eta));
00196 switch (ieta) {
00197 case 0: { p0 = 0.00392416; p1 = 0.00551809; break; }
00198 case 1: { p0 = 0.00390391; p1 = 0.00543244; break; }
00199 case 2: { p0 = 0.0040651; p1 = 0.00406496; break; }
00200 case 3: { p0 = 0.00387782; p1 = 0.00797637; break; }
00201 case 4: { p0 = 0.00376798; p1 = 0.00866894; break; }
00202 case 5: { p0 = 0.0042131; p1 = 0.00462184; break; }
00203 case 6: { p0 = 0.00392579; p1 = 0.00784685; break; }
00204 case 7: { p0 = 0.00370472; p1 = 0.00790174; break; }
00205 case 8: { p0 = 0.00364433; p1 = 0.00928368; break; }
00206 case 9: { p0 = 0.00387578; p1 = 0.00640431; break; }
00207 case 10: { p0 = 0.00382464; p1 = 0.00960763; break; }
00208 case 11: { p0 = 0.0038907; p1 = 0.0104562; break; }
00209 case 12: { p0 = 0.00392525; p1 = 0.0106442; break; }
00210 case 13: { p0 = 0.00400634; p1 = 0.011218; break; }
00211 case 14: { p0 = 0.0036229; p1 = 0.0156403; break; }
00212 case 15: { p0 = 0.00444317; p1 = 0.00832987; break; }
00213 case 16: { p0 = 0.00465492; p1 = 0.0179908; break; }
00214 case 17: { p0 = 0.0049652; p1 = 0.0216647; break; }
00215 case 18: { p0 = 0.0051395; p1 = 0.0233692; break; }
00216 case 19: { p0 = 0.0062917; p1 = 0.0262175; break; }
00217 default: { p0 = 0.00714444; p1 = 0.0253856; break; }
00218 }
00219 return p0+p1*fabs(invPt);
00220 }
00221
00222
00223 double L1MuonPixelTrackFitter::valZip(double curv,
00224 const GlobalPoint& pinner, const GlobalPoint& pouter) const
00225 {
00226
00227
00228
00229 double rho3 = curv*curv*curv;
00230 double r1 = pinner.perp();
00231 double phi1 = r1*curv/2 + pinner.perp2()*r1*rho3/48.;
00232 double r2 = pouter.perp();
00233 double phi2 = r2*curv/2 + pouter.perp2()*r2*rho3/48.;
00234 double z1 = pinner.z();
00235 double z2 = pouter.z();
00236
00237 return z1 - phi1/(phi1-phi2)*(z1-z2);
00238 }
00239
00240
00241 double L1MuonPixelTrackFitter::errZip(double invPt, double eta) const {
00242
00243
00244
00245 double p0,p1;
00246 int ieta = int (10*fabs(eta));
00247 switch (ieta) {
00248 case 0: { p0 = 0.0120743; p1 = 0; break; }
00249 case 1: { p0 = 0.0110343; p1 = 0.0051199; break; }
00250 case 2: { p0 = 0.00846487; p1 = 0.00570084; break; }
00251 case 3: { p0 = 0.00668726; p1 = 0.00331165; break; }
00252 case 4: { p0 = 0.00467126; p1 = 0.00578239; break; }
00253 case 5: { p0 = 0.0043042; p1 = 0.00598517; break; }
00254 case 6: { p0 = 0.00515392; p1 = 0.00495422; break; }
00255 case 7: { p0 = 0.0060843; p1 = 0.00320512; break; }
00256 case 8: { p0 = 0.00564942; p1 = 0.00478876; break; }
00257 case 9: { p0 = 0.00532111; p1 = 0.0073239; break; }
00258 case 10: { p0 = 0.00579429; p1 = 0.00952782; break; }
00259 case 11: { p0 = 0.00614229; p1 = 0.00977795; break; }
00260 case 12: { p0 = 0.00714661; p1 = 0.00550482; break; }
00261 case 13: { p0 = 0.0066593; p1 = 0.00999362; break; }
00262 case 14: { p0 = 0.00634922; p1 = 0.0148156; break; }
00263 case 15: { p0 = 0.00600586; p1 = 0.0318022; break; }
00264 case 16: { p0 = 0.00676919; p1 = 0.027456; break; }
00265 case 17: { p0 = 0.00670066; p1 = 0.0317005; break; }
00266 case 18: { p0 = 0.00752392; p1 = 0.0347714; break; }
00267 case 19: { p0 = 0.00791425; p1 = 0.0566665; break; }
00268 default: { p0 = 0.00882372; p1 = 0.0596858; break; }
00269 }
00270 return p0+p1*fabs(invPt);
00271 }
00272
00273
00274 double L1MuonPixelTrackFitter::valInversePt( double phi0, double phiL1, double eta) const
00275 {
00276 double result = 0.;
00277
00278
00279
00280
00281
00282
00283 double p1,p2,p3;
00284 param(eta, p1, p2, p3);
00285
00286 double dphi = deltaPhi(phiL1,phi0);
00287 if ( fabs(dphi) < 0.01) {
00288 result = -dphi/p1;
00289 } else {
00290 double q = dphi/2./p3;
00291 double p = p1/3./p3;
00292 double D = q*q + p*p*p;
00293 double u = pow(-q+sqrt(D), 1./3.);
00294 double v = -pow(q+sqrt(D), 1./3.);
00295 result = u+v;
00296 }
00297 return result;
00298 }
00299
00300
00301 double L1MuonPixelTrackFitter::errInversePt(double invPt, double eta) const {
00302
00303
00304
00305 double p0,p1;
00306 int ieta = int (10*fabs(eta));
00307 switch (ieta) {
00308 case 0: { p0 = 0.0196835; p1 = 0.00517533; break; }
00309 case 1: { p0 = 0.0266583; p1 = 0.00478101; break; }
00310 case 2: { p0 = 0.0217164; p1 = 0.00545425; break; }
00311 case 3: { p0 = 0.0197547; p1 = 0.00552263; break; }
00312 case 4: { p0 = 0.0208778; p1 = 0.00536009; break; }
00313 case 5: { p0 = 0.024192; p1 = 0.00521709; break; }
00314 case 6: { p0 = 0.0265315; p1 = 0.0051897; break; }
00315 case 7: { p0 = 0.0198071; p1 = 0.00566822; break; }
00316 case 8: { p0 = 0.0361955; p1 = 0.00486352; break; }
00317 case 9: { p0 = 0.037864; p1 = 0.00509094; break; }
00318 case 10: { p0 = 0.0382968; p1 = 0.00612354; break; }
00319 case 11: { p0 = 0.0308326; p1 = 0.0074234; break; }
00320 case 12: { p0 = 0.0248577; p1 = 0.00883049; break; }
00321 case 13: { p0 = 0.0279965; p1 = 0.00888293; break; }
00322 case 14: { p0 = 0.0372582; p1 = 0.00950252; break; }
00323 case 15: { p0 = 0.0281366; p1 = 0.0111501; break; }
00324 case 16: { p0 = 0.0421483; p1 = 0.0109413; break; }
00325 case 17: { p0 = 0.0461798; p1 = 0.0125824; break; }
00326 case 18: { p0 = 0.0530603; p1 = 0.0132638; break; }
00327 case 19: { p0 = 0.0601148; p1 = 0.0147911; break; }
00328 default: { p0 = 0.0552377; p1 = 0.0155574; break; }
00329 }
00330 return p1+p0*fabs(invPt);
00331 }
00332
00333 double L1MuonPixelTrackFitter::findPt(double phi0, double phiL1, double eta, int charge) const {
00334
00335 double dphi_min = fabs(deltaPhi(phi0,phiL1));
00336 double pt_best = 1.;
00337 double pt_cur = 1;
00338 while ( pt_cur < 10000.) {
00339 double phi_exp = phi0+getBending(1./pt_cur, eta, charge);
00340 double dphi = fabs(deltaPhi(phi_exp,phiL1));
00341 if ( dphi < dphi_min) {
00342 pt_best = pt_cur;
00343 dphi_min = dphi;
00344 }
00345 if (pt_cur < 10.) pt_cur += 0.01;
00346 else if (pt_cur < 20.) pt_cur+= 0.025;
00347 else if( pt_cur < 100.) pt_cur+= 0.1;
00348 else pt_cur +=1;
00349 };
00350 return pt_best;
00351 }
00352
00353
00354 double L1MuonPixelTrackFitter::getBending(double invPt, double eta, int charge)
00355 {
00356 double p1, p2, p3;
00357 param(eta,p1,p2,p3);
00358 return charge*p1*invPt + charge*p2*invPt*invPt + charge*p3*invPt*invPt*invPt;
00359 }
00360
00361 double L1MuonPixelTrackFitter::getBendingError(double invPt, double eta)
00362 {
00363 int ieta = int (10*fabs(eta));
00364 double p0,p1;
00365 switch (ieta) {
00366 case 0: { p0 = 0.0196835; p1 = 0.00517533; break; }
00367 case 1: { p0 = 0.0266583; p1 = 0.00478101; break; }
00368 case 2: { p0 = 0.0217164; p1 = 0.00545425; break; }
00369 case 3: { p0 = 0.0197547; p1 = 0.00552263; break; }
00370 case 4: { p0 = 0.0208778; p1 = 0.00536009; break; }
00371 case 5: { p0 = 0.024192; p1 = 0.00521709; break; }
00372 case 6: { p0 = 0.0265315; p1 = 0.0051897; break; }
00373 case 7: { p0 = 0.0198071; p1 = 0.00566822; break; }
00374 case 8: { p0 = 0.0361955; p1 = 0.00486352; break; }
00375 case 9: { p0 = 0.037864; p1 = 0.00509094; break; }
00376 case 10: { p0 = 0.0382968; p1 = 0.00612354; break; }
00377 case 11: { p0 = 0.0308326; p1 = 0.0074234; break; }
00378 case 12: { p0 = 0.0248577; p1 = 0.00883049; break; }
00379 case 13: { p0 = 0.0279965; p1 = 0.00888293; break; }
00380 case 14: { p0 = 0.0372582; p1 = 0.00950252; break; }
00381 case 15: { p0 = 0.0281366; p1 = 0.0111501; break; }
00382 case 16: { p0 = 0.0421483; p1 = 0.0109413; break; }
00383 case 17: { p0 = 0.0461798; p1 = 0.0125824; break; }
00384 case 18: { p0 = 0.0530603; p1 = 0.0132638; break; }
00385 case 19: { p0 = 0.0601148; p1 = 0.0147911; break; }
00386 default: { p0 = 0.0552377; p1 = 0.0155574; break; }
00387 }
00388 return p0+p1*sqr(invPt);
00389 }
00390
00391
00392 void L1MuonPixelTrackFitter::param(double eta, double &p1, double& p2, double& p3)
00393 {
00394 int ieta = int (10*fabs(eta));
00395 switch (ieta) {
00396 case 0: { p1 = -2.68016; p2 = 0; p3 = -12.9653; break; }
00397 case 1: { p1 = -2.67864; p2 = 0; p3 = -12.0036; break; }
00398 case 2: { p1 = -2.72997; p2 = 0; p3 = -10.3468; break; }
00399 case 3: { p1 = -2.68836; p2 = 0; p3 = -12.3369; break; }
00400 case 4: { p1 = -2.66885; p2 = 0; p3 = -11.589; break; }
00401 case 5: { p1 = -2.64932; p2 = 0; p3 = -12.7176; break; }
00402 case 6: { p1 = -2.64513; p2 = 0; p3 = -11.3912; break; }
00403 case 7: { p1 = -2.64487; p2 = 0; p3 = -9.83239; break; }
00404 case 8: { p1 = -2.58875; p2 = 0; p3 = -10.0541; break; }
00405 case 9: { p1 = -2.5551; p2 = 0; p3 = -9.75757; break; }
00406 case 10: { p1 = -2.55294; p2 = 0; p3 = -7.25238; break; }
00407 case 11: { p1 = -2.45333; p2 = 0; p3 = -7.966; break; }
00408 case 12: { p1 = -2.29283; p2 = 0; p3 = -7.03231; break; }
00409 case 13: { p1 = -2.13167; p2 = 0; p3 = -4.29182; break; }
00410 case 14: { p1 = -1.9102; p2 = 0; p3 = -3.21295; break; }
00411 case 15: { p1 = -1.74552; p2 = 0; p3 = -0.531827; break; }
00412 case 16: { p1 = -1.53642; p2 = 0; p3 = -1.74057; break; }
00413 case 17: { p1 = -1.39446; p2 = 0; p3 = -1.56819; break; }
00414 case 18: { p1 = -1.26176; p2 = 0; p3 = -0.598631; break; }
00415 case 19: { p1 = -1.14133; p2 = 0; p3 = -0.0941055; break; }
00416 default: { p1 = -1.02086; p2 = 0; p3 = -0.100491; break; }
00417 }
00418 }
00419
00420 double L1MuonPixelTrackFitter::deltaPhi(double phi1, double phi2) const
00421 {
00422 while ( phi1 >= 2*M_PI) phi1 -= 2*M_PI;
00423 while ( phi2 >= 2*M_PI) phi2 -= 2*M_PI;
00424 while ( phi1 < 0) phi1 += 2*M_PI;
00425 while ( phi2 < 0) phi2 += 2*M_PI;
00426 double dPhi = phi2-phi1;
00427
00428 if ( dPhi > M_PI ) dPhi -= 2*M_PI;
00429 if ( dPhi < -M_PI ) dPhi += 2*M_PI;
00430
00431 return dPhi;
00432 }
00433