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