00001
00002 #include "FastSimulation/BaseParticlePropagator/interface/BaseParticlePropagator.h"
00003
00004 BaseParticlePropagator::BaseParticlePropagator() :
00005 RawParticle(), rCyl(0.), rCyl2(0.), zCyl(0.), bField(0), properDecayTime(1E99)
00006 {;}
00007
00008 BaseParticlePropagator::BaseParticlePropagator(
00009 const RawParticle& myPart,double R, double Z, double B, double t ) :
00010 RawParticle(myPart), rCyl(R), rCyl2(R*R), zCyl(Z), bField(B), properDecayTime(t)
00011 {
00012 init();
00013 }
00014
00015 BaseParticlePropagator::BaseParticlePropagator(
00016 const RawParticle& myPart,double R, double Z, double B) :
00017 RawParticle(myPart), rCyl(R), rCyl2(R*R), zCyl(Z), bField(B), properDecayTime(1E99)
00018 {
00019 init();
00020 }
00021
00022 void
00023 BaseParticlePropagator::init() {
00024
00025
00026 success = 0;
00027
00028 firstLoop = true;
00029
00030 fiducial = true;
00031
00032 decayed = false;
00033
00034 properTime = 0.;
00035
00036 propDir = 1;
00037
00038 debug = false;
00039
00040 }
00041
00042 bool
00043 BaseParticlePropagator::propagate() {
00044
00045
00046
00047
00048
00049 double rPos2 = R2();
00050
00051 if ( onBarrel(rPos2) ) {
00052 success = 1;
00053 return true;
00054 }
00055
00056 if ( onEndcap(rPos2) ) {
00057 success = 2;
00058 return true;
00059 }
00060
00061
00062
00063 if ( fabs(charge()) < 1E-12 || bField < 1E-12 ) {
00064
00065
00066
00067
00068 double pT2 = Perp2();
00069
00070
00071 double b2 = rCyl2 * pT2;
00072 double ac = fabs ( X()*Py() - Y()*Px() );
00073 double ac2 = ac*ac;
00074
00075
00076
00077
00078 if ( ac2 > b2 ) return false;
00079
00080
00081 double delta = std::sqrt(b2 - ac2);
00082 double tplus = -( X()*Px()+Y()*Py() ) + delta;
00083 double tminus = -( X()*Px()+Y()*Py() ) - delta;
00084
00085
00086
00087
00088 double solution = tminus < 0 ? tplus/pT2 : tminus/pT2;
00089 if ( solution < 0. ) return false;
00090
00091
00092
00093 double zProp = Z() + Pz() * solution;
00094 if ( fabs(zProp) > zCyl ) {
00095 tplus = ( zCyl - Z() ) / Pz();
00096 tminus = (-zCyl - Z() ) / Pz();
00097 solution = tminus < 0 ? tplus : tminus;
00098 if ( solution < 0. ) return false;
00099 zProp = Z() + Pz() * solution;
00100 success = 2;
00101 }
00102 else {
00103 success = 1;
00104 }
00105
00106
00107
00108
00109 double delTime = propDir * mass() * solution;
00110 double factor = 1.;
00111 properTime += delTime;
00112 if ( properTime > properDecayTime ) {
00113 factor = 1.-(properTime-properDecayTime)/delTime;
00114 properTime = properDecayTime;
00115 decayed = true;
00116 }
00117
00118
00119
00120
00121 double xProp = X() + Px() * solution * factor;
00122 double yProp = Y() + Py() * solution * factor;
00123 zProp = Z() + Pz() * solution * factor;
00124 double tProp = T() + E() * solution * factor;
00125
00126
00127
00128
00129
00130 if ( success == 2 && xProp*xProp+yProp*yProp > rCyl2 ) {
00131 success = -1;
00132 return true;
00133 }
00134
00135
00136
00137
00138 setVertex( XYZTLorentzVector(xProp,yProp,zProp,tProp) );
00139
00140 return true;
00141 }
00142
00143
00144
00145 else {
00146
00147
00148
00149 double pT = Pt();
00150 double radius = helixRadius(pT);
00151 double phi0 = helixStartPhi();
00152 double xC = helixCentreX(radius,phi0);
00153 double yC = helixCentreY(radius,phi0);
00154 double dist = helixCentreDistToAxis(xC,yC);
00155
00156
00157
00158 if ( fabs ( fabs(radius) - dist ) > rCyl ) return false;
00159
00160
00161
00162
00163 if ( Z() * Pz() > zCyl * fabs(Pz()) ) {
00164 success = -2;
00165 return true;
00166 }
00167
00168 double pZ = Pz();
00169 double phiProp, zProp;
00170
00171
00172
00173 double rProp = std::min(fabs(radius)+dist-0.000001, rCyl);
00174
00175
00176 double sinPhiProp =
00177 (rProp*rProp-radius*radius-dist*dist)/( 2.*dist*radius);
00178
00179
00180 double deltaPhi = 1E99;
00181
00182
00183 if ( 1.-fabs(sinPhiProp) < 1E-9 ) {
00184
00185 double cphi0 = std::cos(phi0);
00186 double sphi0 = std::sin(phi0);
00187 double r0 = (X()*cphi0 + Y()*sphi0)/radius;
00188 double q0 = (X()*sphi0 - Y()*cphi0)/radius;
00189 double rcyl2 = (rCyl2 - X()*X() - Y()*Y())/(radius*radius);
00190 double delta = r0*r0 + rcyl2*(1.-q0);
00191
00192
00193
00194 deltaPhi = radius > 0 ?
00195 ( -r0 + std::sqrt(delta ) ) / (1.-q0) :
00196 ( -r0 - std::sqrt(delta ) ) / (1.-q0);
00197
00198 }
00199
00200
00201 if ( fabs(deltaPhi) > 1E-3 ) {
00202
00203
00204
00205 phiProp = std::asin(sinPhiProp);
00206
00207
00208
00209
00210
00211 phiProp = helixCentrePhi(xC,yC) +
00212 ( inside(rPos2) || onSurface(rPos2) ? phiProp : M_PI-phiProp );
00213
00214
00215
00216
00217 if ( fabs(phiProp - phi0) > 2.*M_PI )
00218 phiProp += ( phiProp > phi0 ? -2.*M_PI : +2.*M_PI );
00219
00220
00221
00222
00223
00224 if ( (phiProp-phi0)*radius < 0.0 )
00225 radius > 0.0 ? phiProp += 2 * M_PI : phiProp -= 2 * M_PI;
00226
00227 } else {
00228
00229
00230 phiProp = phi0 + deltaPhi;
00231
00232 }
00233
00234
00235
00236
00237 zProp = Z() + ( phiProp - phi0 ) * pZ * radius / pT ;
00238 if ( fabs(zProp) > zCyl ) {
00239
00240 zProp = zCyl * fabs(pZ)/pZ;
00241 phiProp = phi0 + (zProp - Z()) / radius * pT / pZ;
00242 success = 2;
00243
00244 } else {
00245
00246
00247
00248
00249
00250 if ( rProp < rCyl ) {
00251
00252 if ( firstLoop || fabs(pZ)/pT < 1E-10 ) {
00253
00254 success = 0;
00255
00256 } else {
00257
00258 zProp = zCyl * fabs(pZ)/pZ;
00259 phiProp = phi0 + (zProp - Z()) / radius * pT / pZ;
00260 success = 2;
00261
00262 }
00263
00264
00265
00266 } else {
00267
00268 success = 1;
00269
00270 }
00271 }
00272
00273
00274
00275
00276
00277
00278 double delTime = propDir * (phiProp-phi0)*radius*mass() / pT;
00279 double factor = 1.;
00280 properTime += delTime;
00281 if ( properTime > properDecayTime ) {
00282 factor = 1.-(properTime-properDecayTime)/delTime;
00283 properTime = properDecayTime;
00284 decayed = true;
00285 }
00286
00287 zProp = Z() + (zProp-Z())*factor;
00288
00289 phiProp = phi0 + (phiProp-phi0)*factor;
00290
00291 double sProp = std::sin(phiProp);
00292 double cProp = std::cos(phiProp);
00293 double xProp = xC + radius * sProp;
00294 double yProp = yC - radius * cProp;
00295 double tProp = T() + (phiProp-phi0)*radius*E()/pT;
00296 double pxProp = pT * cProp;
00297 double pyProp = pT * sProp;
00298
00299
00300
00301
00302
00303 if ( success == 2 && xProp*xProp+yProp*yProp > rCyl2 ) {
00304 success = -1;
00305 return true;
00306 }
00307
00308
00309
00310 setVertex( XYZTLorentzVector(xProp,yProp,zProp,tProp) );
00311 SetXYZT(pxProp,pyProp,pZ,E());
00312
00313
00314 return true;
00315
00316 }
00317 }
00318
00319 bool
00320 BaseParticlePropagator::backPropagate() {
00321
00322
00323 SetXYZT(-Px(),-Py(),-Pz(),E());
00324 setCharge(-charge());
00325 propDir = -1;
00326 bool done = propagate();
00327 SetXYZT(-Px(),-Py(),-Pz(),E());
00328 setCharge(-charge());
00329 propDir = +1;
00330
00331 return done;
00332 }
00333
00334 BaseParticlePropagator
00335 BaseParticlePropagator::propagated() const {
00336
00337 BaseParticlePropagator myPropPart(*this);
00338
00339 myPropPart.firstLoop=false;
00340
00341 myPropPart.propagate();
00342
00343 if (myPropPart.success < 0 )
00344 myPropPart.backPropagate();
00345
00346 return myPropPart;
00347 }
00348
00349 void
00350 BaseParticlePropagator::setPropagationConditions(double R, double Z, bool f) {
00351 rCyl = R;
00352 rCyl2 = R*R;
00353 zCyl = Z;
00354 firstLoop = f;
00355 }
00356
00357 bool
00358 BaseParticlePropagator::propagateToClosestApproach(double x0, double y0, bool first) {
00359
00360
00361 double pT = Pt();
00362 double radius = helixRadius(pT);
00363 double phi0 = helixStartPhi();
00364
00365
00366
00367 double xC = helixCentreX(radius,phi0);
00368 double yC = helixCentreY(radius,phi0);
00369 double distz = helixCentreDistToAxis(xC-x0,yC-y0);
00370 double dist0 = helixCentreDistToAxis(xC,yC);
00371
00372
00373
00374
00375 double rz,r0,z;
00376 if ( charge() != 0.0 && bField != 0.0 ) {
00377 rz = fabs ( fabs(radius) - distz ) + std::sqrt(x0*x0+y0*y0) + 0.0000001;
00378 r0 = fabs ( fabs(radius) - dist0 ) + 0.0000001;
00379 } else {
00380 rz = fabs( Px() * (Y()-y0) - Py() * (X()-x0) ) / Pt();
00381 r0 = fabs( Px() * Y() - Py() * X() ) / Pt();
00382 }
00383
00384 z = 999999.;
00385
00386
00387
00388 setPropagationConditions(rz , z, first);
00389 bool done = backPropagate();
00390
00391
00392 if ( !done ) return done;
00393
00394
00395 if ( fabs(rz-r0) < 1E-10 ) return done;
00396 double dist1 = (X()-x0)*(X()-x0) + (Y()-y0)*(Y()-y0);
00397
00398
00399 if ( dist1 < 1E-10 ) return done;
00400
00401
00402 XYZTLorentzVector vertex1 = vertex();
00403 XYZTLorentzVector momentum1 = momentum();
00404
00405
00406 setPropagationConditions(r0 , z, first);
00407 done = backPropagate();
00408 if ( !done ) return done;
00409
00410
00411
00412 setPropagationConditions(rz , z, first);
00413 done = backPropagate();
00414 if ( !done ) return done;
00415 double dist2 = (X()-x0)*(X()-x0) + (Y()-y0)*(Y()-y0);
00416
00417
00418 if ( dist2 > dist1 ) {
00419 setVertex(vertex1);
00420 SetXYZT(momentum1.X(),momentum1.Y(),momentum1.Z(),momentum1.E());
00421 dist2 = dist1;
00422 }
00423
00424
00425 return done;
00426
00427 }
00428
00429 bool
00430 BaseParticlePropagator::propagateToEcal(bool first) {
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 setPropagationConditions(129.0 , 303.353 , first);
00441 return propagate();
00442
00443 }
00444
00445 bool
00446 BaseParticlePropagator::propagateToPreshowerLayer1(bool first) {
00447
00448
00449
00450
00451
00452
00453
00454
00455 setPropagationConditions(129.0, 303.353 , first);
00456 bool done = propagate();
00457
00458
00459 if ( done && (R2() > 125.0*125.0 || R2() < 45.0*45.0) )
00460 success = 0;
00461
00462 return done;
00463 }
00464
00465 bool
00466 BaseParticlePropagator::propagateToPreshowerLayer2(bool first) {
00467
00468
00469
00470
00471
00472
00473
00474
00475 setPropagationConditions(129.0 , 307.838 , first);
00476 bool done = propagate();
00477
00478
00479 if ( done && (R2() > 125.0*125.0 || R2() < 45.0*45.0 ) )
00480 success = 0;
00481
00482 return done;
00483
00484 }
00485
00486 bool
00487 BaseParticlePropagator::propagateToEcalEntrance(bool first) {
00488
00489
00490
00491
00492
00493
00494 setPropagationConditions(129.0 , 320.9,first);
00495 bool done = propagate();
00496
00497
00498
00499
00500 if ( done && cos2ThetaV() > 0.81230 && success == 1 ) {
00501 setPropagationConditions(152.6 , 320.9, first);
00502 done = propagate();
00503 }
00504
00505
00506
00507 if ( cos2ThetaV() > 0.99014 ) success = 0;
00508
00509 return done;
00510 }
00511
00512 bool
00513 BaseParticlePropagator::propagateToHcalEntrance(bool first) {
00514
00515
00516
00517
00518
00519
00520
00521 setPropagationConditions(177.5 , 335.0, first);
00522 propDir = 0;
00523 bool done = propagate();
00524 propDir = 1;
00525
00526
00527 if (done && success == 2) {
00528 setPropagationConditions(300.0, 400.458, first);
00529 propDir = 0;
00530 done = propagate();
00531 propDir = 1;
00532 }
00533
00534
00535
00536
00537 if ( done && cos2ThetaV() > 0.99014 ) success = 0;
00538
00539 return done;
00540 }
00541
00542 bool
00543 BaseParticlePropagator::propagateToVFcalEntrance(bool first) {
00544
00545
00546
00547
00548
00549 setPropagationConditions(400.0 , 1110.0, first);
00550 propDir = 0;
00551 bool done = propagate();
00552 propDir = 1;
00553
00554 if (!done) success = 0;
00555
00556
00557
00558
00559 double c2teta = cos2ThetaV();
00560 if ( done && ( c2teta < 0.99014 || c2teta > 0.9998755 ) ) success = 0;
00561
00562 return done;
00563 }
00564
00565 bool
00566 BaseParticlePropagator::propagateToHcalExit(bool first) {
00567
00568
00569
00570
00571
00572
00573
00574 setPropagationConditions(263.9 , 554.1, first);
00575
00576 propDir = 0;
00577 bool done = propagate();
00578 propDir = 1;
00579
00580 return done;
00581 }
00582
00583 bool
00584 BaseParticlePropagator::propagateToNominalVertex(const XYZTLorentzVector& v)
00585 {
00586
00587
00588
00589 if ( charge() == 0. || bField == 0.) return false;
00590
00591
00592 double dx = X()-v.X();
00593 double dy = Y()-v.Y();
00594 double phi = std::atan2(dy,dx) + std::asin ( std::sqrt(dx*dx+dy*dy)/(2.*helixRadius()) );
00595
00596
00597 double pT = pt();
00598
00599
00600 SetPx(pT*std::cos(phi));
00601 SetPy(pT*std::sin(phi));
00602
00603 return propagateToClosestApproach(v.X(),v.Y());
00604
00605 }
00606
00607 bool
00608 BaseParticlePropagator::propagateToBeamCylinder(const XYZTLorentzVector& v, double radius)
00609 {
00610
00611
00612 if ( charge() == 0. || bField == 0.)
00613 return fabs( Px() * Y() - Py() * X() ) / Pt() < radius;
00614
00615
00616
00617
00618
00619 double r = radius;
00620 double r2 = r*r;
00621 double r4 = r2*r2;
00622
00623 double dx = X()-v.X();
00624 double dy = Y()-v.Y();
00625 double dz = Z()-v.Z();
00626 double Sxy = X()*v.X() + Y()*v.Y();
00627 double Dxy = Y()*v.X() - X()*v.Y();
00628 double Dxy2 = Dxy*Dxy;
00629 double Sxy2 = Sxy*Sxy;
00630 double SDxy = dx*dx + dy*dy;
00631 double SSDxy = std::sqrt(SDxy);
00632 double ATxy = std::atan2(dy,dx);
00633
00634 double a = r2 - Dxy2/SDxy;
00635 double b = r * (r2 - Sxy);
00636 double c = r4 - 2.*Sxy*r2 + Sxy2 + Dxy2;
00637
00638
00639
00640 std::vector<double> helixRs(4,static_cast<double>(0.));
00641 helixRs[0] = (b - std::sqrt(b*b - a*c))/(2.*a);
00642 helixRs[1] = (b + std::sqrt(b*b - a*c))/(2.*a);
00643 helixRs[2] = -helixRs[0];
00644 helixRs[3] = -helixRs[1];
00645
00646 std::vector<double> helixPhis(4,static_cast<double>(0.));
00647 helixPhis[0] = std::asin ( SSDxy/(2.*helixRs[0]) );
00648 helixPhis[1] = std::asin ( SSDxy/(2.*helixRs[1]) );
00649 helixPhis[2] = -helixPhis[0];
00650 helixPhis[3] = -helixPhis[1];
00651
00652 double solution1=0.;
00653 double solution2=0.;
00654 double phi1=0.;
00655 double phi2=0.;
00656
00657 for ( unsigned int i=0; i<4; ++i ) {
00658 helixPhis[i] = ATxy + helixPhis[i];
00659
00660 double xC = helixCentreX(helixRs[i],helixPhis[i]);
00661 double yC = helixCentreY(helixRs[i],helixPhis[i]);
00662
00663 double dist = helixCentreDistToAxis(xC, yC);
00664
00665
00666
00667
00668
00669
00670
00671 if ( fabs( fabs(fabs(helixRs[i]) - dist) -fabs(radius) ) < 1e-6 ) {
00672
00673 if ( solution1 == 0. ) {
00674 solution1 = helixRs[i];
00675 phi1 = helixPhis[i];
00676
00677 } else if ( solution2 == 0. ) {
00678 if ( helixRs[i] < solution1 ) {
00679 solution2 = solution1;
00680 solution1 = helixRs[i];
00681 phi2 = phi1;
00682 phi1 = helixPhis[i];
00683 } else {
00684 solution2 = helixRs[i];
00685 phi2 = helixPhis[i];
00686 }
00687
00688 } else {
00689 std::cout << "warning !!! More than two solutions for this track !!! " << std::endl;
00690 }
00691 }
00692 }
00693
00694
00695 double pT = 0.;
00696 double helixPhi = 0.;
00697 double helixR = 0.;
00698
00699 if ( solution1*solution2 == 0. ) {
00700 std::cout << "warning !!! Less than two solution for this track! "
00701 << solution1 << " " << solution2 << std::endl;
00702 return false;
00703
00704 } else if ( solution1*solution2 < 0. ) {
00705 pT = 1000.;
00706 double norm = pT/std::sqrt(SDxy);
00707 setCharge(+1.);
00708 SetXYZT(dx*norm,dy*norm,dz*norm,0.);
00709 SetE(std::sqrt(Vect().Mag2()));
00710
00711 } else {
00712 if (solution1<0.) {
00713 helixR = solution1;
00714 helixPhi = phi1;
00715 pT = fabs(solution1) * 1e-5 * c_light() *bField;
00716 setCharge(+1.);
00717 } else {
00718 helixR = solution2;
00719 helixPhi = phi2;
00720 pT = fabs(solution2) * 1e-5 * c_light() *bField;
00721 setCharge(-1.);
00722 }
00723 double norm = pT/std::sqrt(SDxy);
00724 SetXYZT(pT*std::cos(helixPhi),pT*std::sin(helixPhi),dz*norm,0.);
00725 SetE(std::sqrt(Vect().Mag2()));
00726 }
00727
00728
00729 return propagateToClosestApproach();
00730
00731 }
00732
00733 double
00734 BaseParticlePropagator::xyImpactParameter(double x0, double y0) const {
00735
00736 double ip=0.;
00737 double pT = Pt();
00738
00739 if ( charge() != 0.0 && bField != 0.0 ) {
00740 double radius = helixRadius(pT);
00741 double phi0 = helixStartPhi();
00742
00743
00744 double xC = helixCentreX(radius,phi0);
00745 double yC = helixCentreY(radius,phi0);
00746 double distz = helixCentreDistToAxis(xC-x0,yC-y0);
00747 ip = distz - fabs(radius);
00748 } else {
00749 ip = fabs( Px() * (Y()-y0) - Py() * (X()-x0) ) / pT;
00750 }
00751
00752 return ip;
00753
00754 }