00001
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "MagneticField/Engine/interface/MagneticField.h"
00022 #include "MagneticField/VolumeBasedEngine/interface/VolumeBasedMagneticField.h"
00023 #include "MagneticField/VolumeGeometry/interface/MagVolume.h"
00024 #include "MagneticField/Interpolation/interface/MFGrid.h"
00025
00026 #include "Utilities/Timing/interface/TimingReport.h"
00027
00028 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00029 #include "DataFormats/GeometrySurface/interface/Plane.h"
00030 #include "DataFormats/GeometrySurface/interface/Cone.h"
00031
00032 #include "TrackingTools/GeomPropagators/interface/PropagationExceptions.h"
00033
00034 #include "TrackPropagation/SteppingHelixPropagator/interface/SteppingHelixPropagator.h"
00035
00036 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00037
00038 #include <sstream>
00039 #include <typeinfo>
00040
00041 SteppingHelixPropagator::SteppingHelixPropagator() :
00042 Propagator(anyDirection)
00043 {
00044 field_ = 0;
00045 }
00046
00047 SteppingHelixPropagator::SteppingHelixPropagator(const MagneticField* field,
00048 PropagationDirection dir):
00049 Propagator(dir),
00050 unit66_(AlgebraicMatrixID())
00051 {
00052 field_ = field;
00053 vbField_ = dynamic_cast<const VolumeBasedMagneticField*>(field_);
00054 covRot_ = AlgebraicMatrix66();
00055 dCTransform_ = unit66_;
00056 debug_ = false;
00057 noMaterialMode_ = false;
00058 noErrorPropagation_ = false;
00059 applyRadX0Correction_ = true;
00060 useMagVolumes_ = true;
00061 useIsYokeFlag_ = true;
00062 useMatVolumes_ = true;
00063 useInTeslaFromMagField_ = false;
00064 returnTangentPlane_ = true;
00065 sendLogWarning_ = false;
00066 useTuningForL2Speed_ = false;
00067 for (int i = 0; i <= MAX_POINTS; i++){
00068 svBuf_[i].cov = AlgebraicSymMatrix66();
00069 svBuf_[i].matDCov = AlgebraicSymMatrix66();
00070 svBuf_[i].isComplete = true;
00071 svBuf_[i].isValid_ = true;
00072 svBuf_[i].hasErrorPropagated_ = !noErrorPropagation_;
00073 }
00074 defaultStep_ = 5.;
00075
00076 ecShiftPos_ = 0;
00077 ecShiftNeg_ = 0;
00078
00079 }
00080
00081 TrajectoryStateOnSurface
00082 SteppingHelixPropagator::propagate(const FreeTrajectoryState& ftsStart, const Plane& pDest) const {
00083 return propagateWithPath(ftsStart, pDest).first;
00084 }
00085
00086 TrajectoryStateOnSurface
00087 SteppingHelixPropagator::propagate(const FreeTrajectoryState& ftsStart, const Cylinder& cDest) const
00088 {
00089 return propagateWithPath(ftsStart, cDest).first;
00090 }
00091
00092 FreeTrajectoryState
00093 SteppingHelixPropagator::propagate(const FreeTrajectoryState& ftsStart, const GlobalPoint& pDest) const
00094 {
00095 return propagateWithPath(ftsStart, pDest).first;
00096 }
00097
00098 FreeTrajectoryState
00099 SteppingHelixPropagator::propagate(const FreeTrajectoryState& ftsStart,
00100 const GlobalPoint& pDest1, const GlobalPoint& pDest2) const
00101 {
00102 return propagateWithPath(ftsStart, pDest1, pDest2).first;
00103 }
00104
00105 FreeTrajectoryState
00106 SteppingHelixPropagator::propagate(const FreeTrajectoryState& ftsStart,
00107 const reco::BeamSpot& beamSpot) const
00108 {
00109 return propagateWithPath(ftsStart, beamSpot).first;
00110 }
00111
00112
00113 std::pair<TrajectoryStateOnSurface, double>
00114 SteppingHelixPropagator::propagateWithPath(const FreeTrajectoryState& ftsStart,
00115 const Plane& pDest) const {
00116
00117 setIState(SteppingHelixStateInfo(ftsStart));
00118
00119 const StateInfo& svCurrent = propagate(svBuf_[0], pDest);
00120
00121 return TsosPP(svCurrent.getStateOnSurface(pDest), svCurrent.path());
00122 }
00123
00124 std::pair<TrajectoryStateOnSurface, double>
00125 SteppingHelixPropagator::propagateWithPath(const FreeTrajectoryState& ftsStart,
00126 const Cylinder& cDest) const {
00127
00128 setIState(SteppingHelixStateInfo(ftsStart));
00129
00130 const StateInfo& svCurrent = propagate(svBuf_[0], cDest);
00131
00132 return TsosPP(svCurrent.getStateOnSurface(cDest, returnTangentPlane_), svCurrent.path());
00133 }
00134
00135
00136 std::pair<FreeTrajectoryState, double>
00137 SteppingHelixPropagator::propagateWithPath(const FreeTrajectoryState& ftsStart,
00138 const GlobalPoint& pDest) const {
00139 setIState(SteppingHelixStateInfo(ftsStart));
00140
00141 const StateInfo& svCurrent = propagate(svBuf_[0], pDest);
00142
00143 FreeTrajectoryState ftsDest;
00144 svCurrent.getFreeState(ftsDest);
00145
00146 return FtsPP(ftsDest, svCurrent.path());
00147 }
00148
00149 std::pair<FreeTrajectoryState, double>
00150 SteppingHelixPropagator::propagateWithPath(const FreeTrajectoryState& ftsStart,
00151 const GlobalPoint& pDest1, const GlobalPoint& pDest2) const {
00152
00153 if ((pDest1-pDest2).mag() < 1e-10){
00154 if (sendLogWarning_){
00155 edm::LogWarning("SteppingHelixPropagator")<<"Can't propagate: the points should be at a bigger distance"
00156 <<std::endl;
00157 }
00158 return FtsPP();
00159 }
00160 setIState(SteppingHelixStateInfo(ftsStart));
00161
00162 const StateInfo& svCurrent = propagate(svBuf_[0], pDest1, pDest2);
00163
00164 FreeTrajectoryState ftsDest;
00165 svCurrent.getFreeState(ftsDest);
00166
00167 return FtsPP(ftsDest, svCurrent.path());
00168 }
00169
00170
00171 std::pair<FreeTrajectoryState, double>
00172 SteppingHelixPropagator::propagateWithPath(const FreeTrajectoryState& ftsStart,
00173 const reco::BeamSpot& beamSpot) const {
00174 GlobalPoint pDest1(beamSpot.x0(), beamSpot.y0(), beamSpot.z0());
00175 GlobalPoint pDest2(pDest1.x() + beamSpot.dxdz()*1e3,
00176 pDest1.y() + beamSpot.dydz()*1e3,
00177 pDest1.z() + 1e3);
00178 return propagateWithPath(ftsStart, pDest1, pDest2);
00179 }
00180
00181 const SteppingHelixStateInfo&
00182 SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
00183 const Surface& sDest) const {
00184
00185 if (! sStart.isValid()){
00186 if (sendLogWarning_){
00187 edm::LogWarning("SteppingHelixPropagator")<<"Can't propagate: invalid input state"
00188 <<std::endl;
00189 }
00190 return invalidState_;
00191 }
00192
00193 const Plane* pDest = dynamic_cast<const Plane*>(&sDest);
00194 if (pDest != 0) return propagate(sStart, *pDest);
00195
00196 const Cylinder* cDest = dynamic_cast<const Cylinder*>(&sDest);
00197 if (cDest != 0) return propagate(sStart, *cDest);
00198
00199 throw PropagationException("The surface is neither Cylinder nor Plane");
00200
00201 }
00202
00203 const SteppingHelixStateInfo&
00204 SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
00205 const Plane& pDest) const {
00206
00207 if (! sStart.isValid()){
00208 if (sendLogWarning_){
00209 edm::LogWarning("SteppingHelixPropagator")<<"Can't propagate: invalid input state"
00210 <<std::endl;
00211 }
00212 return invalidState_;
00213 }
00214 setIState(sStart);
00215
00216 GlobalPoint rPlane = pDest.position();
00217 GlobalVector nPlane(pDest.rotation().zx(), pDest.rotation().zy(), pDest.rotation().zz());
00218
00219 double pars[6] = { pDest.position().x(), pDest.position().y(), pDest.position().z(),
00220 pDest.rotation().zx(), pDest.rotation().zy(), pDest.rotation().zz() };
00221
00222 propagate(PLANE_DT, pars);
00223
00224
00225
00226 double lDir = 0;
00227 if (sStart.path() < svBuf_[cIndex_(nPoints_-1)].path()) lDir = 1.;
00228 if (sStart.path() > svBuf_[cIndex_(nPoints_-1)].path()) lDir = -1.;
00229 svBuf_[cIndex_(nPoints_-1)].dir = lDir;
00230 return svBuf_[cIndex_(nPoints_-1)];
00231 }
00232
00233 const SteppingHelixStateInfo&
00234 SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
00235 const Cylinder& cDest) const {
00236
00237 if (! sStart.isValid()){
00238 if (sendLogWarning_){
00239 edm::LogWarning("SteppingHelixPropagator")<<"Can't propagate: invalid input state"
00240 <<std::endl;
00241 }
00242 return invalidState_;
00243 }
00244 setIState(sStart);
00245
00246 double pars[6] = {0,0,0,0,0,0};
00247 pars[RADIUS_P] = cDest.radius();
00248
00249
00250 propagate(RADIUS_DT, pars);
00251
00252
00253
00254 double lDir = 0;
00255 if (sStart.path() < svBuf_[cIndex_(nPoints_-1)].path()) lDir = 1.;
00256 if (sStart.path() > svBuf_[cIndex_(nPoints_-1)].path()) lDir = -1.;
00257 svBuf_[cIndex_(nPoints_-1)].dir = lDir;
00258 return svBuf_[cIndex_(nPoints_-1)];
00259 }
00260
00261 const SteppingHelixStateInfo&
00262 SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
00263 const GlobalPoint& pDest) const {
00264
00265 if (! sStart.isValid()){
00266 if (sendLogWarning_){
00267 edm::LogWarning("SteppingHelixPropagator")<<"Can't propagate: invalid input state"
00268 <<std::endl;
00269 }
00270 return invalidState_;
00271 }
00272 setIState(sStart);
00273
00274 double pars[6] = {pDest.x(), pDest.y(), pDest.z(), 0, 0, 0};
00275
00276
00277 propagate(POINT_PCA_DT, pars);
00278
00279 return svBuf_[cIndex_(nPoints_-1)];
00280 }
00281
00282 const SteppingHelixStateInfo&
00283 SteppingHelixPropagator::propagate(const SteppingHelixStateInfo& sStart,
00284 const GlobalPoint& pDest1, const GlobalPoint& pDest2) const {
00285
00286 if ((pDest1-pDest2).mag() < 1e-10 || !sStart.isValid()){
00287 if (sendLogWarning_){
00288 if ((pDest1-pDest2).mag() < 1e-10)
00289 edm::LogWarning("SteppingHelixPropagator")<<"Can't propagate: points are too close"
00290 <<std::endl;
00291 if (!sStart.isValid())
00292 edm::LogWarning("SteppingHelixPropagator")<<"Can't propagate: invalid input state"
00293 <<std::endl;
00294 }
00295 return invalidState_;
00296 }
00297 setIState(sStart);
00298
00299 double pars[6] = {pDest1.x(), pDest1.y(), pDest1.z(),
00300 pDest2.x(), pDest2.y(), pDest2.z()};
00301
00302 propagate(LINE_PCA_DT, pars);
00303
00304 return svBuf_[cIndex_(nPoints_-1)];
00305 }
00306
00307 void SteppingHelixPropagator::setIState(const SteppingHelixStateInfo& sStart) const {
00308 nPoints_ = 0;
00309 svBuf_[cIndex_(nPoints_)] = sStart;
00310 if (sStart.isComplete ) {
00311 svBuf_[cIndex_(nPoints_)] = sStart;
00312 nPoints_++;
00313 } else {
00314 loadState(svBuf_[cIndex_(nPoints_)], sStart.p3, sStart.r3, sStart.q, sStart.cov,
00315 propagationDirection());
00316 nPoints_++;
00317 }
00318 svBuf_[cIndex_(0)].hasErrorPropagated_ = sStart.hasErrorPropagated_ & !noErrorPropagation_;
00319 }
00320
00321 SteppingHelixPropagator::Result
00322 SteppingHelixPropagator::propagate(SteppingHelixPropagator::DestType type,
00323 const double pars[6], double epsilon) const{
00324
00325 static const std::string metname = "SteppingHelixPropagator";
00326 StateInfo* svCurrent = &svBuf_[cIndex_(nPoints_-1)];
00327
00328
00329 double tanDist = 0;
00330 double dist = 0;
00331 PropagationDirection refDirection = anyDirection;
00332 Result result = refToDest(type, (*svCurrent), pars, dist, tanDist, refDirection);
00333
00334 if (result != SteppingHelixStateInfo::OK || fabs(dist) > 1e6){
00335 svCurrent->status_ = result;
00336 if (fabs(dist) > 1e6) svCurrent->status_ = SteppingHelixStateInfo::INACC;
00337 svCurrent->isValid_ = false;
00338 svCurrent->field = field_;
00339 if (sendLogWarning_){
00340 edm::LogWarning(metname)<<" Failed after first refToDest check with status "
00341 <<SteppingHelixStateInfo::ResultName[result]
00342 <<std::endl;
00343 }
00344 return result;
00345 }
00346
00347 result = SteppingHelixStateInfo::UNDEFINED;
00348 bool makeNextStep = true;
00349 double dStep = defaultStep_;
00350 PropagationDirection dir,oldDir;
00351 dir = propagationDirection();
00352 oldDir = dir;
00353 int nOsc = 0;
00354
00355 double distMag = 1e12;
00356 double tanDistMag = 1e12;
00357
00358 double distMat = 1e12;
00359 double tanDistMat = 1e12;
00360
00361 double tanDistNextCheck = -0.1;
00362 double tanDistMagNextCheck = -0.1;
00363 double tanDistMatNextCheck = -0.1;
00364 double oldDStep = 0;
00365 PropagationDirection oldRefDirection = propagationDirection();
00366
00367 Result resultToMat = SteppingHelixStateInfo::UNDEFINED;
00368 Result resultToMag = SteppingHelixStateInfo::UNDEFINED;
00369
00370 bool isFirstStep = true;
00371 bool expectNewMagVolume = false;
00372
00373 int loopCount = 0;
00374 while (makeNextStep){
00375 dStep = defaultStep_;
00376 svCurrent = &svBuf_[cIndex_(nPoints_-1)];
00377 double curZ = svCurrent->r3.z();
00378 double curR = svCurrent->r3.perp();
00379 if ( fabs(curZ) < 440 && curR < 260) dStep = defaultStep_*2;
00380
00381
00382
00383 if (useTuningForL2Speed_){
00384 dStep = 100.;
00385 if (! useIsYokeFlag_ && fabs(curZ) < 667 && curR > 380 && curR < 850){
00386 dStep = 5*(1+0.2*svCurrent->p3.mag());
00387 }
00388 }
00389
00390
00391
00392 tanDistNextCheck -= oldDStep;
00393 tanDistMagNextCheck -= oldDStep;
00394 tanDistMatNextCheck -= oldDStep;
00395
00396 if (tanDistNextCheck < 0){
00397
00398 if (! isFirstStep) refToDest(type, (*svCurrent), pars, dist, tanDist, refDirection);
00399
00400 if (fabs(tanDist/dist) > 4) tanDist *= fabs(dist/tanDist*4.);
00401
00402 tanDistNextCheck = fabs(tanDist)*0.5 - 0.5;
00403
00404 if (tanDistNextCheck > defaultStep_*20. ) tanDistNextCheck = defaultStep_*20.;
00405 oldRefDirection = refDirection;
00406 } else {
00407 tanDist = tanDist > 0. ? tanDist - oldDStep : tanDist + oldDStep;
00408 refDirection = oldRefDirection;
00409 if (debug_) LogTrace(metname)<<"Skipped refToDest: guess tanDist = "<<tanDist
00410 <<" next check at "<<tanDistNextCheck<<std::endl;
00411 }
00413 double fastSkipDist = fabs(dist) > fabs(tanDist) ? tanDist : dist;
00414
00415 if (propagationDirection() == anyDirection){
00416 dir = refDirection;
00417 } else {
00418 dir = propagationDirection();
00419 if (fabs(tanDist)<0.1 && refDirection != dir ){
00420
00421 dir = refDirection;
00422 if (debug_) LogTrace(metname)<<"NOTE: overstepped last time: switch direction (can do it if within 1 mm)"<<std::endl;
00423 }
00424 }
00425
00426 if (useMagVolumes_ && ! (fabs(dist) < fabs(epsilon))){
00427 if (tanDistMagNextCheck < 0){
00428 resultToMag = refToMagVolume((*svCurrent), dir, distMag, tanDistMag, fabs(fastSkipDist), expectNewMagVolume);
00429
00430 if (fabs(tanDistMag/distMag) > 4) tanDistMag *= fabs(distMag/tanDistMag*4.);
00431
00432 tanDistMagNextCheck = fabs(tanDistMag)*0.5-0.5;
00433
00434 if (tanDistMagNextCheck > defaultStep_*20.
00435 || fabs(dist) < fabs(distMag)
00436 || resultToMag ==SteppingHelixStateInfo::INACC)
00437 tanDistMagNextCheck = defaultStep_*20 > fabs(fastSkipDist) ? fabs(fastSkipDist) : defaultStep_*20;;
00438 if (resultToMag != SteppingHelixStateInfo::INACC
00439 && resultToMag != SteppingHelixStateInfo::OK) tanDistMagNextCheck = -1;
00440 } else {
00441
00442 tanDistMag = tanDistMag > 0. ? tanDistMag - oldDStep : tanDistMag + oldDStep;
00443 if (debug_) LogTrace(metname)<<"Skipped refToMag: guess tanDistMag = "<<tanDistMag
00444 <<" next check at "<<tanDistMagNextCheck;
00445 }
00446 }
00447
00448 if (useMatVolumes_ && ! (fabs(dist) < fabs(epsilon))){
00449 if (tanDistMatNextCheck < 0){
00450 resultToMat = refToMatVolume((*svCurrent), dir, distMat, tanDistMat, fabs(fastSkipDist));
00451
00452 if (fabs(tanDistMat/distMat) > 4) tanDistMat *= fabs(distMat/tanDistMat*4.);
00453
00454 tanDistMatNextCheck = fabs(tanDistMat)*0.5-0.5;
00455
00456 if (tanDistMatNextCheck > defaultStep_*20.
00457 || fabs(dist) < fabs(distMat)
00458 || resultToMat ==SteppingHelixStateInfo::INACC )
00459 tanDistMatNextCheck = defaultStep_*20 > fabs(fastSkipDist) ? fabs(fastSkipDist) : defaultStep_*20;
00460 if (resultToMat != SteppingHelixStateInfo::INACC
00461 && resultToMat != SteppingHelixStateInfo::OK) tanDistMatNextCheck = -1;
00462 } else {
00463
00464 tanDistMat = tanDistMat > 0. ? tanDistMat - oldDStep : tanDistMat + oldDStep;
00465 if (debug_) LogTrace(metname)<<"Skipped refToMat: guess tanDistMat = "<<tanDistMat
00466 <<" next check at "<<tanDistMatNextCheck;
00467 }
00468 }
00469
00470 double rDotP = svCurrent->r3.dot(svCurrent->p3);
00471 if ((fabs(curZ) > 1.5e3 || curR >800.)
00472 && ((dir == alongMomentum && rDotP > 0)
00473 || (dir == oppositeToMomentum && rDotP < 0) )
00474 ){
00475 dStep = fabs(tanDist) -1e-12;
00476 }
00477 double tanDistMin = fabs(tanDist);
00478 if (tanDistMin > fabs(tanDistMag)+0.05 &&
00479 (resultToMag == SteppingHelixStateInfo::OK || resultToMag == SteppingHelixStateInfo::WRONG_VOLUME)){
00480 tanDistMin = fabs(tanDistMag)+0.05;
00481 expectNewMagVolume = true;
00482 } else expectNewMagVolume = false;
00483
00484 if (tanDistMin > fabs(tanDistMat)+0.05 && resultToMat == SteppingHelixStateInfo::OK){
00485 tanDistMin = fabs(tanDistMat)+0.05;
00486 if (expectNewMagVolume) expectNewMagVolume = false;
00487 }
00488
00489 if (tanDistMin*fabs(svCurrent->dEdx) > 0.5*svCurrent->p3.mag()){
00490 tanDistMin = 0.5*svCurrent->p3.mag()/fabs(svCurrent->dEdx);
00491 if (expectNewMagVolume) expectNewMagVolume = false;
00492 }
00493
00494
00495
00496 double tanDistMinLazy = fabs(tanDistMin);
00497 if ((type == POINT_PCA_DT || type == LINE_PCA_DT)
00498 && fabs(tanDist) < 2.*fabs(tanDistMin) ){
00499
00500 tanDistMinLazy = fabs(tanDistMin)*0.5;
00501 }
00502
00503 if (fabs(tanDistMinLazy) < dStep){
00504 dStep = fabs(tanDistMinLazy);
00505 }
00506
00507
00508 oldDStep = dStep;
00509
00510 if (dStep > 1e-10 && ! (fabs(dist) < fabs(epsilon))){
00511 StateInfo* svNext = &svBuf_[cIndex_(nPoints_)];
00512 makeAtomStep((*svCurrent), (*svNext), dStep, dir, HEL_AS_F);
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 nPoints_++; svCurrent = &svBuf_[cIndex_(nPoints_-1)];
00526 if (oldDir != dir){
00527 nOsc++;
00528 tanDistNextCheck = -1;
00529 tanDistMagNextCheck = -1;
00530 tanDistMatNextCheck = -1;
00531 }
00532 oldDir = dir;
00533 }
00534
00535 if (nOsc>1 && fabs(dStep)>epsilon){
00536 if (debug_) LogTrace(metname)<<"Ooops"<<std::endl;
00537 }
00538
00539 if (fabs(dist) < fabs(epsilon) ) result = SteppingHelixStateInfo::OK;
00540
00541 if ((type == POINT_PCA_DT || type == LINE_PCA_DT )
00542 && fabs(dStep) < fabs(epsilon) ){
00543
00544 double nextDist = 0;
00545 double nextTanDist = 0;
00546 PropagationDirection nextRefDirection = anyDirection;
00547 StateInfo* svNext = &svBuf_[cIndex_(nPoints_)];
00548 makeAtomStep((*svCurrent), (*svNext), 1., dir, HEL_AS_F);
00549 nPoints_++; svCurrent = &svBuf_[cIndex_(nPoints_-1)];
00550 refToDest(type, (*svCurrent), pars, nextDist, nextTanDist, nextRefDirection);
00551 if ( fabs(nextDist) > fabs(dist)){
00552 nPoints_--; svCurrent = &svBuf_[cIndex_(nPoints_-1)];
00553 result = SteppingHelixStateInfo::OK;
00554 if (debug_){
00555 LogTrace(metname)<<"Found real local minimum in PCA"<<std::endl;
00556 }
00557 } else {
00558
00559 dStep = defaultStep_;
00560 if (debug_){
00561 LogTrace(metname)<<"Found branch point in PCA"<<std::endl;
00562 }
00563 }
00564 }
00565
00566 if (nPoints_ > MAX_STEPS*1./defaultStep_ || loopCount > MAX_STEPS*100
00567 || nOsc > 6 ) result = SteppingHelixStateInfo::FAULT;
00568
00569 if (svCurrent->p3.mag() < 0.1 ) result = SteppingHelixStateInfo::RANGEOUT;
00570
00571 curZ = svCurrent->r3.z();
00572 curR = svCurrent->r3.perp();
00573 if ( curR > 20000 || fabs(curZ) > 20000 ) result = SteppingHelixStateInfo::INACC;
00574
00575 makeNextStep = result == SteppingHelixStateInfo::UNDEFINED;
00576 svCurrent->status_ = result;
00577 svCurrent->isValid_ = (result == SteppingHelixStateInfo::OK || makeNextStep );
00578 svCurrent->field = field_;
00579
00580 isFirstStep = false;
00581 loopCount++;
00582 }
00583
00584 if (sendLogWarning_ && result != SteppingHelixStateInfo::OK){
00585 edm::LogWarning(metname)<<" Propagation failed with status "
00586 <<SteppingHelixStateInfo::ResultName[result]
00587 <<std::endl;
00588 if (result == SteppingHelixStateInfo::RANGEOUT)
00589 edm::LogWarning(metname)<<" Momentum at last point is too low (<0.1) p_last = "
00590 <<svCurrent->p3.mag()
00591 <<std::endl;
00592 if (result == SteppingHelixStateInfo::INACC)
00593 edm::LogWarning(metname)<<" Went too far: the last point is at "<<svCurrent->r3
00594 <<std::endl;
00595 if (result == SteppingHelixStateInfo::FAULT && nOsc > 6)
00596 edm::LogWarning(metname)<<" Infinite loop condidtion detected: going in cycles. Break after 6 cycles"
00597 <<std::endl;
00598 if (result == SteppingHelixStateInfo::FAULT && nPoints_ > MAX_STEPS*1./defaultStep_)
00599 edm::LogWarning(metname)<<" Tired to go farther. Made too many steps: more than "
00600 <<MAX_STEPS*1./defaultStep_
00601 <<std::endl;
00602
00603 }
00604
00605 if (debug_){
00606 switch (type) {
00607 case RADIUS_DT:
00608 LogTrace(metname)<<"going to radius "<<pars[RADIUS_P]<<std::endl;
00609 break;
00610 case Z_DT:
00611 LogTrace(metname)<<"going to z "<<pars[Z_P]<<std::endl;
00612 break;
00613 case PATHL_DT:
00614 LogTrace(metname)<<"going to pathL "<<pars[PATHL_P]<<std::endl;
00615 break;
00616 case PLANE_DT:
00617 {
00618 Point rPlane(pars[0], pars[1], pars[2]);
00619 Vector nPlane(pars[3], pars[4], pars[5]);
00620 LogTrace(metname)<<"going to plane r0:"<<rPlane<<" n:"<<nPlane<<std::endl;
00621 }
00622 break;
00623 case POINT_PCA_DT:
00624 {
00625 Point rDest(pars[0], pars[1], pars[2]);
00626 LogTrace(metname)<<"going to PCA to point "<<rDest<<std::endl;
00627 }
00628 break;
00629 case LINE_PCA_DT:
00630 {
00631 Point rDest1(pars[0], pars[1], pars[2]);
00632 Point rDest2(pars[3], pars[4], pars[5]);
00633 LogTrace(metname)<<"going to PCA to line "<<rDest1<<" - "<<rDest2<<std::endl;
00634 }
00635 break;
00636 default:
00637 LogTrace(metname)<<"going to NOT IMPLEMENTED"<<std::endl;
00638 break;
00639 }
00640 LogTrace(metname)<<"Made "<<nPoints_-1<<" steps and stopped at(cur step) "<<svCurrent->r3<<" nOsc "<<nOsc<<std::endl;
00641 }
00642
00643 return result;
00644 }
00645
00646 void SteppingHelixPropagator::loadState(SteppingHelixPropagator::StateInfo& svCurrent,
00647 const SteppingHelixPropagator::Vector& p3,
00648 const SteppingHelixPropagator::Point& r3, int charge,
00649 const AlgebraicSymMatrix66& cov, PropagationDirection dir) const{
00650 static const std::string metname = "SteppingHelixPropagator";
00651
00652 svCurrent.q = charge;
00653 svCurrent.p3 = p3;
00654 svCurrent.r3 = r3;
00655 svCurrent.dir = dir == alongMomentum ? 1.: -1.;
00656
00657 svCurrent.path_ = 0;
00658 svCurrent.radPath_ = 0;
00659
00660 GlobalPoint gPointNegZ(svCurrent.r3.x(), svCurrent.r3.y(), -fabs(svCurrent.r3.z()));
00661 GlobalPoint gPointNorZ(svCurrent.r3.x(), svCurrent.r3.y(), svCurrent.r3.z());
00662
00663 GlobalVector bf;
00664
00665 if (useMagVolumes_){
00666 if (vbField_ ){
00667 if (vbField_->isZSymmetric()){
00668 svCurrent.magVol = vbField_->findVolume(gPointNegZ);
00669 } else {
00670 svCurrent.magVol = vbField_->findVolume(gPointNorZ);
00671 }
00672 if (useIsYokeFlag_){
00673 double curRad = svCurrent.r3.perp();
00674 if (curRad > 380 && curRad < 850 && fabs(svCurrent.r3.z()) < 667){
00675 svCurrent.isYokeVol = isYokeVolume(svCurrent.magVol);
00676 } else {
00677 svCurrent.isYokeVol = false;
00678 }
00679 }
00680 } else {
00681 edm::LogWarning(metname)<<"Failed to cast into VolumeBasedMagneticField: fall back to the default behavior"<<std::endl;
00682 svCurrent.magVol = 0;
00683 }
00684 if (debug_){
00685 LogTrace(metname)<<"Got volume at "<<svCurrent.magVol<<std::endl;
00686 }
00687 }
00688
00689 if (useMagVolumes_ && svCurrent.magVol != 0 && ! useInTeslaFromMagField_){
00690 if (vbField_->isZSymmetric()){
00691 bf = svCurrent.magVol->inTesla(gPointNegZ);
00692 } else {
00693 bf = svCurrent.magVol->inTesla(gPointNorZ);
00694 }
00695 if (r3.z() > 0 && vbField_->isZSymmetric() ){
00696 svCurrent.bf.set(-bf.x(), -bf.y(), bf.z());
00697 } else {
00698 svCurrent.bf.set(bf.x(), bf.y(), bf.z());
00699 }
00700 } else {
00701 GlobalPoint gPoint(r3.x(), r3.y(), r3.z());
00702 bf = field_->inTesla(gPoint);
00703 svCurrent.bf.set(bf.x(), bf.y(), bf.z());
00704 }
00705 if (svCurrent.bf.mag() < 1e-6) svCurrent.bf.set(0., 0., 1e-6);
00706
00707
00708
00709 double dEdXPrime = 0;
00710 double dEdx = 0;
00711 double radX0 = 0;
00712 MatBounds rzLims;
00713 dEdx = getDeDx(svCurrent, dEdXPrime, radX0, rzLims);
00714 svCurrent.dEdx = dEdx; svCurrent.dEdXPrime = dEdXPrime;
00715 svCurrent.radX0 = radX0;
00716 svCurrent.rzLims = rzLims;
00717
00718 svCurrent.cov =cov;
00719
00720 svCurrent.isComplete = true;
00721 svCurrent.isValid_ = true;
00722
00723 if (debug_){
00724 LogTrace(metname)<<"Loaded at path: "<<svCurrent.path()<<" radPath: "<<svCurrent.radPath()
00725 <<" p3 "<<" pt: "<<svCurrent.p3.perp()<<" phi: "<<svCurrent.p3.phi()
00726 <<" eta: "<<svCurrent.p3.eta()
00727 <<" "<<svCurrent.p3
00728 <<" r3: "<<svCurrent.r3
00729 <<" bField: "<<svCurrent.bf.mag()
00730 <<std::endl;
00731 LogTrace(metname)<<"Input Covariance in Global RF "<<cov<<std::endl;
00732 }
00733 }
00734
00735 void SteppingHelixPropagator::getNextState(const SteppingHelixPropagator::StateInfo& svPrevious,
00736 SteppingHelixPropagator::StateInfo& svNext,
00737 double dP, const SteppingHelixPropagator::Vector& tau,
00738 const SteppingHelixPropagator::Vector& drVec, double dS, double dX0,
00739 const AlgebraicMatrix66& dCovTransform) const{
00740 static const std::string metname = "SteppingHelixPropagator";
00741 svNext.q = svPrevious.q;
00742 svNext.dir = dS > 0.0 ? 1.: -1.;
00743 svNext.p3 = tau; svNext.p3*=(svPrevious.p3.mag() - svNext.dir*fabs(dP));
00744
00745 svNext.r3 = svPrevious.r3; svNext.r3 += drVec;
00746
00747 svNext.path_ = svPrevious.path() + dS;
00748 svNext.radPath_ = svPrevious.radPath() + dX0;
00749
00750 GlobalPoint gPointNegZ(svNext.r3.x(), svNext.r3.y(), -fabs(svNext.r3.z()));
00751 GlobalPoint gPointNorZ(svNext.r3.x(), svNext.r3.y(), svNext.r3.z());
00752
00753 GlobalVector bf;
00754
00755 if (useMagVolumes_){
00756 if (vbField_ != 0){
00757 if (vbField_->isZSymmetric()){
00758 svNext.magVol = vbField_->findVolume(gPointNegZ);
00759 } else {
00760 svNext.magVol = vbField_->findVolume(gPointNorZ);
00761 }
00762 if (useIsYokeFlag_){
00763 double curRad = svNext.r3.perp();
00764 if (curRad > 380 && curRad < 850 && fabs(svNext.r3.z()) < 667){
00765 svNext.isYokeVol = isYokeVolume(svNext.magVol);
00766 } else {
00767 svNext.isYokeVol = false;
00768 }
00769 }
00770 } else {
00771 LogTrace(metname)<<"Failed to cast into VolumeBasedMagneticField"<<std::endl;
00772 svNext.magVol = 0;
00773 }
00774 if (debug_){
00775 LogTrace(metname)<<"Got volume at "<<svNext.magVol<<std::endl;
00776 }
00777 }
00778
00779 if (useMagVolumes_ && svNext.magVol != 0 && ! useInTeslaFromMagField_){
00780 if (vbField_->isZSymmetric()){
00781 bf = svNext.magVol->inTesla(gPointNegZ);
00782 } else {
00783 bf = svNext.magVol->inTesla(gPointNorZ);
00784 }
00785 if (svNext.r3.z() > 0 && vbField_->isZSymmetric() ){
00786 svNext.bf.set(-bf.x(), -bf.y(), bf.z());
00787 } else {
00788 svNext.bf.set(bf.x(), bf.y(), bf.z());
00789 }
00790 } else {
00791 GlobalPoint gPoint(svNext.r3.x(), svNext.r3.y(), svNext.r3.z());
00792 bf = field_->inTesla(gPoint);
00793 svNext.bf.set(bf.x(), bf.y(), bf.z());
00794 }
00795 if (svNext.bf.mag() < 1e-6) svNext.bf.set(0., 0., 1e-6);
00796
00797
00798 double dEdXPrime = 0;
00799 double dEdx = 0;
00800 double radX0 = 0;
00801 MatBounds rzLims;
00802 dEdx = getDeDx(svNext, dEdXPrime, radX0, rzLims);
00803 svNext.dEdx = dEdx; svNext.dEdXPrime = dEdXPrime;
00804 svNext.radX0 = radX0;
00805 svNext.rzLims = rzLims;
00806
00807
00808 svNext.hasErrorPropagated_ = svPrevious.hasErrorPropagated_;
00809 if (svPrevious.hasErrorPropagated_){
00810
00811 AlgebraicMatrix66 tmp = dCovTransform*svPrevious.cov;
00812 ROOT::Math::AssignSym::Evaluate(svNext.cov, tmp*ROOT::Math::Transpose(dCovTransform));
00813
00814 svNext.cov += svPrevious.matDCov;
00815 } else {
00816
00817
00818 }
00819
00820 if (debug_){
00821 LogTrace(metname)<<"Now at path: "<<svNext.path()<<" radPath: "<<svNext.radPath()
00822 <<" p3 "<<" pt: "<<svNext.p3.perp()<<" phi: "<<svNext.p3.phi()
00823 <<" eta: "<<svNext.p3.eta()
00824 <<" "<<svNext.p3
00825 <<" r3: "<<svNext.r3
00826 <<" dPhi: "<<acos(svNext.p3.unit().dot(svPrevious.p3.unit()))
00827 <<" bField: "<<svNext.bf.mag()
00828 <<" dedx: "<<svNext.dEdx
00829 <<std::endl;
00830 LogTrace(metname)<<"New Covariance "<<svNext.cov<<std::endl;
00831 LogTrace(metname)<<"Transf by dCovTransform "<<dCovTransform<<std::endl;
00832 }
00833 }
00834
00835 void SteppingHelixPropagator::setRep(SteppingHelixPropagator::Basis& rep,
00836 const SteppingHelixPropagator::Vector& tau) const{
00837 Vector zRep(0., 0., 1.);
00838 rep.lX = tau;
00839 rep.lY = zRep.cross(tau); rep.lY *= 1./tau.perp();
00840 rep.lZ = rep.lX.cross(rep.lY);
00841 }
00842
00843 bool SteppingHelixPropagator::makeAtomStep(SteppingHelixPropagator::StateInfo& svCurrent,
00844 SteppingHelixPropagator::StateInfo& svNext,
00845 double dS,
00846 PropagationDirection dir,
00847 SteppingHelixPropagator::Fancy fancy) const{
00848 static const std::string metname = "SteppingHelixPropagator";
00849 if (debug_){
00850 LogTrace(metname)<<"Make atom step "<<svCurrent.path()<<" with step "<<dS<<" in direction "<<dir<<std::endl;
00851 }
00852
00853 double dP = 0;
00854 Vector tau = svCurrent.p3; tau *= 1./tau.mag();
00855 Vector tauNext(tau);
00856 Vector drVec;
00857
00858 dS = dir == alongMomentum ? fabs(dS) : -fabs(dS);
00859
00860
00861 double radX0 = 1e24;
00862
00863 switch (fancy){
00864 case HEL_AS_F:
00865 case HEL_ALL_F:{
00866 double p0 = svCurrent.p3.mag();
00867 double b0 = svCurrent.bf.mag();
00868
00869
00870 double phi = 0.0029979*svCurrent.q*b0/p0*dS/2.;
00871 bool phiSmall = fabs(phi) < 3e-8;
00872
00873 double cosPhi = cos(phi);
00874 double sinPhi = sin(phi);
00875
00876 double oneLessCosPhi = 1.-cosPhi;
00877 double oneLessCosPhiOPhi = oneLessCosPhi/phi;
00878 double sinPhiOPhi = sinPhi/phi;
00879 double phiLessSinPhiOPhi = 1 - sinPhiOPhi;
00880 if (phiSmall){
00881 oneLessCosPhi = 0.5*phi*phi;
00882 oneLessCosPhiOPhi = 0.5*phi;
00883 sinPhiOPhi = 1. - phi*phi/6.;
00884 phiLessSinPhiOPhi = phi*phi/6.;
00885 }
00886
00887 Vector bHat = svCurrent.bf; bHat *= 1./bHat.mag();
00888 Vector btVec(bHat.cross(tau));
00889 Vector bbtVec(bHat.cross(btVec));
00890
00891
00892 drVec = tau; drVec += bbtVec*phiLessSinPhiOPhi; drVec -= btVec*oneLessCosPhiOPhi;
00893 drVec *= dS/2.;
00894
00895 double dEdx = svCurrent.dEdx;
00896 double dEdXPrime = svCurrent.dEdXPrime;
00897 radX0 = svCurrent.radX0;
00898 dP = dEdx*dS;
00899
00900
00901 drVec += svCurrent.r3;
00902 GlobalVector bfGV;
00903 Vector bf;
00904
00905 if (useMagVolumes_ && svCurrent.magVol != 0 && ! useInTeslaFromMagField_){
00906
00907 if (vbField_->isZSymmetric()){
00908 bfGV = svCurrent.magVol->inTesla(GlobalPoint(drVec.x(), drVec.y(), -fabs(drVec.z())));
00909 } else {
00910 bfGV = svCurrent.magVol->inTesla(GlobalPoint(drVec.x(), drVec.y(), drVec.z()));
00911 }
00912 if (drVec.z() > 0 && vbField_->isZSymmetric()){
00913 bf.set(-bfGV.x(), -bfGV.y(), bfGV.z());
00914 } else {
00915 bf.set(bfGV.x(), bfGV.y(), bfGV.z());
00916 }
00917 } else {
00918 bfGV = field_->inTesla(GlobalPoint(drVec.x(), drVec.y(), drVec.z()));
00919 bf.set(bfGV.x(), bfGV.y(), bfGV.z());
00920 }
00921 b0 = bf.mag();
00922 if (b0 < 1e-6) {
00923 b0 = 1e-6;
00924 bf.set(0., 0., 1e-6);
00925 }
00926 if (debug_){
00927 LogTrace(metname)<<"Improved b "<<b0
00928 <<" at r3 "<<drVec<<std::endl;
00929 }
00930
00931 if (fabs((b0-svCurrent.bf.mag())*dS) > 1){
00932
00933 if (debug_){
00934 LogTrace(metname)<<"Large bf*dS change "<<fabs((b0-svCurrent.bf.mag())*dS)
00935 <<" --> recalc dedx"<<std::endl;
00936 }
00937 svNext.r3 = drVec;
00938 svNext.bf = bf;
00939 svNext.p3 = svCurrent.p3;
00940 svNext.isYokeVol = svCurrent.isYokeVol;
00941 MatBounds rzTmp;
00942 dEdx = getDeDx(svNext, dEdXPrime, radX0, rzTmp);
00943 dP = dEdx*dS;
00944 if (debug_){
00945 LogTrace(metname)<<"New dEdX= "<<dEdx
00946 <<" dP= "<<dP
00947 <<" for p0 "<<p0<<std::endl;
00948 }
00949 }
00950
00951 p0 += dP/2.; p0 = p0 < 1e-2 ? 1e-2 : p0;
00952
00953 phi = 0.0029979*svCurrent.q*b0/p0*dS;
00954 phiSmall = fabs(phi) < 3e-8;
00955
00956 if (phiSmall){
00957 sinPhi = phi;
00958 cosPhi = 1. -phi*phi/2;
00959 oneLessCosPhi = 0.5*phi*phi;
00960 oneLessCosPhiOPhi = 0.5*phi;
00961 sinPhiOPhi = 1. - phi*phi/6.;
00962 phiLessSinPhiOPhi = phi*phi/6.;
00963 }else {
00964 cosPhi = cos(phi);
00965 sinPhi = sin(phi);
00966 oneLessCosPhi = 1.-cosPhi;
00967 oneLessCosPhiOPhi = oneLessCosPhi/phi;
00968 sinPhiOPhi = sinPhi/phi;
00969 phiLessSinPhiOPhi = 1. - sinPhiOPhi;
00970 }
00971
00972 bHat = bf; bHat *= 1./bHat.mag();
00973 btVec = bHat.cross(tau);
00974 bbtVec = bHat.cross(btVec);
00975
00976 tauNext = tau; tauNext += bbtVec*oneLessCosPhi; tauNext -= btVec*sinPhi;
00977 drVec = tau; drVec += bbtVec*phiLessSinPhiOPhi; drVec -= btVec*oneLessCosPhiOPhi;
00978 drVec *= dS;
00979
00980
00981 if (svCurrent.hasErrorPropagated_){
00982 double theta02 = 14.e-3/p0*sqrt(fabs(dS)/radX0);
00983 theta02 *=theta02;
00984 if (applyRadX0Correction_){
00985
00986
00987
00988
00989 double x0 = fabs(svCurrent.radPath());
00990 double dX0 = fabs(dS)/radX0;
00991 double alphaX0 = 13.6e-3/p0; alphaX0 *= alphaX0;
00992 double betaX0 = 0.038;
00993 theta02 = dX0*alphaX0*(1+betaX0*log(x0+1))*(1 + betaX0*log(x0+1) + 2.*betaX0*x0/(x0+1) );
00994 }
00995
00996 double epsilonP0 = 1.+ dP/p0;
00997 double omegaP0 = -dP/p0 + dS*dEdXPrime;
00998
00999
01000 double dsp = dS/p0;
01001
01002 Vector tbtVec(tau.cross(btVec));
01003
01004 dCTransform_ = unit66_;
01005
01006
01007 dCTransform_(0,3) = dsp*(bHat.x()*tbtVec.x()
01008 + cosPhi*tau.x()*bbtVec.x()
01009 + ((1.-bHat.x()*bHat.x()) + phi*tau.x()*btVec.x())*sinPhiOPhi);
01010
01011 dCTransform_(0,4) = dsp*(bHat.z()*oneLessCosPhiOPhi + bHat.x()*tbtVec.y()
01012 + cosPhi*tau.y()*bbtVec.x()
01013 + (-bHat.x()*bHat.y() + phi*tau.y()*btVec.x())*sinPhiOPhi);
01014 dCTransform_(0,5) = dsp*(-bHat.y()*oneLessCosPhiOPhi + bHat.x()*tbtVec.z()
01015 + cosPhi*tau.z()*bbtVec.x()
01016 + (-bHat.x()*bHat.z() + phi*tau.z()*btVec.x())*sinPhiOPhi);
01017
01018 dCTransform_(1,3) = dsp*(-bHat.z()*oneLessCosPhiOPhi + bHat.y()*tbtVec.x()
01019 + cosPhi*tau.x()*bbtVec.y()
01020 + (-bHat.x()*bHat.y() + phi*tau.x()*btVec.y())*sinPhiOPhi);
01021 dCTransform_(1,4) = dsp*(bHat.y()*tbtVec.y()
01022 + cosPhi*tau.y()*bbtVec.y()
01023 + ((1.-bHat.y()*bHat.y()) + phi*tau.y()*btVec.y())*sinPhiOPhi);
01024 dCTransform_(1,5) = dsp*(bHat.x()*oneLessCosPhiOPhi + bHat.y()*tbtVec.z()
01025 + cosPhi*tau.z()*bbtVec.y()
01026 + (-bHat.y()*bHat.z() + phi*tau.z()*btVec.y())*sinPhiOPhi);
01027
01028 dCTransform_(2,3) = dsp*(bHat.y()*oneLessCosPhiOPhi + bHat.z()*tbtVec.x()
01029 + cosPhi*tau.x()*bbtVec.z()
01030 + (-bHat.x()*bHat.z() + phi*tau.x()*btVec.z())*sinPhiOPhi);
01031 dCTransform_(2,4) = dsp*(-bHat.x()*oneLessCosPhiOPhi + bHat.z()*tbtVec.y()
01032 + cosPhi*tau.y()*bbtVec.z()
01033 + (-bHat.y()*bHat.z() + phi*tau.y()*btVec.z())*sinPhiOPhi);
01034 dCTransform_(2,5) = dsp*(bHat.z()*tbtVec.z()
01035 + cosPhi*tau.z()*bbtVec.z()
01036 + ((1.-bHat.z()*bHat.z()) + phi*tau.z()*btVec.z())*sinPhiOPhi);
01037
01038
01039 dCTransform_(3,3) = epsilonP0*(1. - oneLessCosPhi*(1.-bHat.x()*bHat.x())
01040 + phi*tau.x()*(cosPhi*btVec.x() - sinPhi*bbtVec.x()))
01041 + omegaP0*tau.x()*tauNext.x();
01042 dCTransform_(3,4) = epsilonP0*(bHat.x()*bHat.y()*oneLessCosPhi + bHat.z()*sinPhi
01043 + phi*tau.y()*(cosPhi*btVec.x() - sinPhi*bbtVec.x()))
01044 + omegaP0*tau.y()*tauNext.x();
01045 dCTransform_(3,5) = epsilonP0*(bHat.x()*bHat.z()*oneLessCosPhi - bHat.y()*sinPhi
01046 + phi*tau.z()*(cosPhi*btVec.x() - sinPhi*bbtVec.x()))
01047 + omegaP0*tau.z()*tauNext.x();
01048
01049 dCTransform_(4,3) = epsilonP0*(bHat.x()*bHat.y()*oneLessCosPhi - bHat.z()*sinPhi
01050 + phi*tau.x()*(cosPhi*btVec.y() - sinPhi*bbtVec.y()))
01051 + omegaP0*tau.x()*tauNext.y();
01052 dCTransform_(4,4) = epsilonP0*(1. - oneLessCosPhi*(1.-bHat.y()*bHat.y())
01053 + phi*tau.y()*(cosPhi*btVec.y() - sinPhi*bbtVec.y()))
01054 + omegaP0*tau.y()*tauNext.y();
01055 dCTransform_(4,5) = epsilonP0*(bHat.y()*bHat.z()*oneLessCosPhi + bHat.x()*sinPhi
01056 + phi*tau.z()*(cosPhi*btVec.y() - sinPhi*bbtVec.y()))
01057 + omegaP0*tau.z()*tauNext.y();
01058
01059 dCTransform_(5,3) = epsilonP0*(bHat.x()*bHat.z()*oneLessCosPhi + bHat.y()*sinPhi
01060 + phi*tau.x()*(cosPhi*btVec.z() - sinPhi*bbtVec.z()))
01061 + omegaP0*tau.x()*tauNext.z();
01062 dCTransform_(5,4) = epsilonP0*(bHat.y()*bHat.z()*oneLessCosPhi - bHat.x()*sinPhi
01063 + phi*tau.y()*(cosPhi*btVec.z() - sinPhi*bbtVec.z()))
01064 + omegaP0*tau.y()*tauNext.z();
01065 dCTransform_(5,5) = epsilonP0*(1. - oneLessCosPhi*(1.-bHat.z()*bHat.z())
01066 + phi*tau.z()*(cosPhi*btVec.z() - sinPhi*bbtVec.z()))
01067 + omegaP0*tau.z()*tauNext.z();
01068
01069
01070 Basis rep; setRep(rep, tauNext);
01071
01072
01073
01074
01075 double mulRR = theta02*dS*dS/3.;
01076 double mulRP = theta02*fabs(dS)*p0/2.;
01077 double mulPP = theta02*p0*p0;
01078 double losPP = dP*dP*1.6/fabs(dS)*(1.0 + p0*1e-3);
01079
01080
01081
01082
01083
01084
01085 svCurrent.matDCov(0,0) = mulRR*(rep.lY.x()*rep.lY.x() + rep.lZ.x()*rep.lZ.x());
01086 svCurrent.matDCov(0,1) = mulRR*(rep.lY.x()*rep.lY.y() + rep.lZ.x()*rep.lZ.y());
01087 svCurrent.matDCov(0,2) = mulRR*(rep.lY.x()*rep.lY.z() + rep.lZ.x()*rep.lZ.z());
01088 svCurrent.matDCov(1,1) = mulRR*(rep.lY.y()*rep.lY.y() + rep.lZ.y()*rep.lZ.y());
01089 svCurrent.matDCov(1,2) = mulRR*(rep.lY.y()*rep.lY.z() + rep.lZ.y()*rep.lZ.z());
01090 svCurrent.matDCov(2,2) = mulRR*(rep.lY.z()*rep.lY.z() + rep.lZ.z()*rep.lZ.z());
01091
01092
01093 svCurrent.matDCov(3,3) = mulPP*(rep.lY.x()*rep.lY.x() + rep.lZ.x()*rep.lZ.x())
01094 + losPP*rep.lX.x()*rep.lX.x();
01095 svCurrent.matDCov(3,4) = mulPP*(rep.lY.x()*rep.lY.y() + rep.lZ.x()*rep.lZ.y())
01096 + losPP*rep.lX.x()*rep.lX.y();
01097 svCurrent.matDCov(3,5) = mulPP*(rep.lY.x()*rep.lY.z() + rep.lZ.x()*rep.lZ.z())
01098 + losPP*rep.lX.x()*rep.lX.z();
01099 svCurrent.matDCov(4,4) = mulPP*(rep.lY.y()*rep.lY.y() + rep.lZ.y()*rep.lZ.y())
01100 + losPP*rep.lX.y()*rep.lX.y();
01101 svCurrent.matDCov(4,5) = mulPP*(rep.lY.y()*rep.lY.z() + rep.lZ.y()*rep.lZ.z())
01102 + losPP*rep.lX.y()*rep.lX.z();
01103 svCurrent.matDCov(5,5) = mulPP*(rep.lY.z()*rep.lY.z() + rep.lZ.z()*rep.lZ.z())
01104 + losPP*rep.lX.z()*rep.lX.z();
01105
01106
01107 svCurrent.matDCov(0,3) = mulRP*(rep.lY.x()*rep.lY.x() + rep.lZ.x()*rep.lZ.x());
01108 svCurrent.matDCov(0,4) = mulRP*(rep.lY.x()*rep.lY.y() + rep.lZ.x()*rep.lZ.y());
01109 svCurrent.matDCov(0,5) = mulRP*(rep.lY.x()*rep.lY.z() + rep.lZ.x()*rep.lZ.z());
01110 svCurrent.matDCov(1,3) = mulRP*(rep.lY.x()*rep.lY.y() + rep.lZ.x()*rep.lZ.y());
01111 svCurrent.matDCov(1,4) = mulRP*(rep.lY.y()*rep.lY.y() + rep.lZ.y()*rep.lZ.y());
01112 svCurrent.matDCov(1,5) = mulRP*(rep.lY.y()*rep.lY.z() + rep.lZ.y()*rep.lZ.z());
01113 svCurrent.matDCov(2,3) = mulRP*(rep.lY.x()*rep.lY.z() + rep.lZ.x()*rep.lZ.z());
01114 svCurrent.matDCov(2,4) = mulRP*(rep.lY.y()*rep.lY.z() + rep.lZ.y()*rep.lZ.z());
01115 svCurrent.matDCov(2,5) = mulRP*(rep.lY.z()*rep.lY.z() + rep.lZ.z()*rep.lZ.z());
01116
01117 }
01118 break;
01119 }
01120
01121
01122
01123
01124 default:
01125 break;
01126 }
01127
01128 double pMag = svCurrent.p3.mag();
01129
01130 if (dir == oppositeToMomentum) dP = fabs(dP);
01131 else if( dP < 0) {
01132 dP = -dP > pMag ? -pMag+1e-5 : dP;
01133 }
01134
01135 getNextState(svCurrent, svNext, dP, tauNext, drVec, dS, dS/radX0,
01136 dCTransform_);
01137 return true;
01138 }
01139
01140 double SteppingHelixPropagator::getDeDx(const SteppingHelixPropagator::StateInfo& sv,
01141 double& dEdXPrime, double& radX0,
01142 MatBounds& rzLims) const{
01143 radX0 = 1.e24;
01144 dEdXPrime = 0.;
01145 rzLims = MatBounds();
01146 if (noMaterialMode_) return 0;
01147
01148 double dEdx = 0.;
01149
01150 double lR = sv.r3.perp();
01151 double lZ = fabs(sv.r3.z());
01152
01153
01154
01155 double p0 = sv.p3.mag();
01156
01157
01158 double dEdX_mat = -(11.4 + 0.96*fabs(log(p0*2.8)) + 0.033*p0*(1.0 - pow(p0, -0.33)) )*1e-3;
01159
01160 double dEdX_HCal = 0.95*dEdX_mat;
01161 double dEdX_ECal = 0.45*dEdX_mat;
01162 double dEdX_coil = 0.35*dEdX_mat;
01163 double dEdX_Fe = dEdX_mat;
01164 double dEdX_MCh = 0.053*dEdX_mat;
01165 double dEdX_Trk = 0.0114*dEdX_mat;
01166 double dEdX_Air = 2E-4*dEdX_mat;
01167 double dEdX_Vac = 0.0;
01168
01169 double radX0_HCal = 1.44/0.8;
01170 double radX0_ECal = 0.89/0.7;
01171 double radX0_coil = 4.;
01172 double radX0_Fe = 1.76;
01173 double radX0_MCh = 1e3;
01174 double radX0_Trk = 320.;
01175 double radX0_Air = 3.e4;
01176 double radX0_Vac = 3.e9;
01177
01178
01179
01180 if (! (lR < 380 && lZ < 785)){
01181 if (lZ > 785 ) rzLims = MatBounds(0, 1e4, 785, 1e4);
01182 if (lZ < 785 ) rzLims = MatBounds(380, 1e4, 0, 785);
01183 }
01184
01185
01186
01187 double ecShift = sv.r3.z() > 0 ? fabs(ecShiftPos_) : fabs(ecShiftNeg_);
01188
01189
01190
01191 if (lR < 2.9){
01192 dEdx = dEdX_Vac; radX0 = radX0_Vac;
01193 rzLims = MatBounds(0, 2.9, 0, 1E4);
01194 }
01195 else if (lR < 129){
01196 if (lZ < 294){
01197 rzLims = MatBounds(2.9, 129, 0, 294);
01198 dEdx = dEdX_Trk; radX0 = radX0_Trk;
01199
01200
01201
01202 double lEtaDet = fabs(sv.r3.eta());
01203 double scaleRadX = lEtaDet > 1.5 ? 0.7724 : sin(2.*atan(exp(-0.5*lEtaDet)));
01204 scaleRadX *= scaleRadX;
01205 if (lEtaDet > 2 && lZ > 20) scaleRadX *= (lEtaDet-1.);
01206 if (lEtaDet > 2.5 && lZ > 20) scaleRadX *= (lEtaDet-1.);
01207 radX0 *= scaleRadX;
01208 }
01209
01210 else if ( lZ < 294 + ecShift ){
01211
01212 rzLims = MatBounds(2.9, 129, 294, 294 + ecShift);
01213 dEdx = dEdX_Air; radX0 = radX0_Air;
01214 }
01215 else if (lZ < 372 + ecShift){
01216 rzLims = MatBounds(2.9, 129, 294 + ecShift, 372 + ecShift);
01217 dEdx = dEdX_ECal; radX0 = radX0_ECal;
01218 }
01219 else if (lZ < 398 + ecShift){
01220 rzLims = MatBounds(2.9, 129, 372 + ecShift, 398 + ecShift);
01221 dEdx = dEdX_HCal*0.05; radX0 = radX0_Air;
01222 }
01223 else if (lZ < 555 + ecShift){
01224 rzLims = MatBounds(2.9, 129, 398 + ecShift, 555 + ecShift);
01225 dEdx = dEdX_HCal*0.96; radX0 = radX0_HCal/0.96;
01226 }
01227 else {
01228
01229
01230
01231 if (lZ < 568 + ecShift) rzLims = MatBounds(2.9, 129, 555 + ecShift, 568 + ecShift);
01232 else if (lZ < 625 + ecShift){
01233 if (lR < 85 + ecShift) rzLims = MatBounds(2.9, 85, 568 + ecShift, 625 + ecShift);
01234 else rzLims = MatBounds(85, 129, 568 + ecShift, 625 + ecShift);
01235 } else if (lZ < 785 + ecShift) rzLims = MatBounds(2.9, 129, 625 + ecShift, 785 + ecShift);
01236 else if (lZ < 1500 + ecShift) rzLims = MatBounds(2.9, 129, 785 + ecShift, 1500 + ecShift);
01237 else rzLims = MatBounds(2.9, 129, 1500 + ecShift, 1E4);
01238
01239
01240 if (! (lZ > 568 + ecShift && lZ < 625 + ecShift && lR > 85 )
01241 && ! (lZ > 785 + ecShift && lZ < 850 + ecShift && lR > 118)) {dEdx = dEdX_Fe; radX0 = radX0_Fe; }
01242 else { dEdx = dEdX_MCh; radX0 = radX0_MCh; }
01243 }
01244 }
01245 else if (lR < 287){
01246 if (lZ < 372 + ecShift && lR < 177){
01247 if (lZ < 304) rzLims = MatBounds(129, 177, 0, 304);
01248 else if (lZ < 343){
01249 if (lR < 135 ) rzLims = MatBounds(129, 135, 304, 343);
01250 else if (lR < 172 ){
01251 if (lZ < 311 ) rzLims = MatBounds(135, 172, 304, 311);
01252 else rzLims = MatBounds(135, 172, 311, 343);
01253 } else {
01254 if (lZ < 328) rzLims = MatBounds(172, 177, 304, 328);
01255 else rzLims = MatBounds(172, 177, 328, 343);
01256 }
01257 }
01258 else if ( lZ < 343 + ecShift){
01259 rzLims = MatBounds(129, 177, 343, 343 + ecShift);
01260 }
01261 else {
01262 if (lR < 156 ) rzLims = MatBounds(129, 156, 343 + ecShift, 372 + ecShift);
01263 else if ( (lZ - 343 - ecShift) > (lR - 156)*1.38 )
01264 rzLims = MatBounds(156, 177, 127.72 + ecShift, 372 + ecShift, atan(1.38), 0);
01265 else rzLims = MatBounds(156, 177, 343 + ecShift, 127.72 + ecShift, 0, atan(1.38));
01266 }
01267
01268 if (!(lR > 135 && lZ <343 + ecShift && lZ > 304 )
01269 && ! (lR > 156 && lZ < 372 + ecShift && lZ > 343 + ecShift && ((lZ-343. - ecShift )< (lR-156.)*1.38)))
01270 {
01271
01272 double cosThetaEquiv = 0.8/sqrt(1.+lZ*lZ/lR/lR) + 0.2;
01273 if (lZ > 343) cosThetaEquiv = 1.;
01274 dEdx = dEdX_ECal*cosThetaEquiv; radX0 = radX0_ECal/cosThetaEquiv;
01275 }
01276 else {
01277 if ( (lZ > 304 && lZ < 328 && lR < 177 && lR > 135)
01278 && ! (lZ > 311 && lR < 172) ) {dEdx = dEdX_Fe; radX0 = radX0_Fe; }
01279 else if ( lZ > 343 && lZ < 343 + ecShift) { dEdx = dEdX_Air; radX0 = radX0_Air; }
01280 else {dEdx = dEdX_ECal*0.2; radX0 = radX0_Air;}
01281 }
01282 }
01283 else if (lZ < 554 + ecShift){
01284 if (lR < 177){
01285 if ( lZ > 372 + ecShift && lZ < 398 + ecShift )rzLims = MatBounds(129, 177, 372 + ecShift, 398 + ecShift);
01286 else if (lZ < 548 + ecShift) rzLims = MatBounds(129, 177, 398 + ecShift, 548 + ecShift);
01287 else rzLims = MatBounds(129, 177, 548 + ecShift, 554 + ecShift);
01288 }
01289 else if (lR < 193){
01290 if ((lZ - 307) < (lR - 177.)*1.739) rzLims = MatBounds(177, 193, 0, -0.803, 0, atan(1.739));
01291 else if ( lZ < 389) rzLims = MatBounds(177, 193, -0.803, 389, atan(1.739), 0.);
01292 else if ( lZ < 389 + ecShift) rzLims = MatBounds(177, 193, 389, 389 + ecShift);
01293 else if ( lZ < 548 + ecShift ) rzLims = MatBounds(177, 193, 389 + ecShift, 548 + ecShift);
01294 else rzLims = MatBounds(177, 193, 548 + ecShift, 554 + ecShift);
01295 }
01296 else if (lR < 264){
01297 double anApex = 375.7278 - 193./1.327;
01298 if ( (lZ - 375.7278) < (lR - 193.)/1.327) rzLims = MatBounds(193, 264, 0, anApex, 0, atan(1./1.327));
01299 else if ( (lZ - 392.7278 ) < (lR - 193.)/1.327)
01300 rzLims = MatBounds(193, 264, anApex, anApex+17., atan(1./1.327), atan(1./1.327));
01301 else if ( (lZ - 392.7278 - ecShift ) < (lR - 193.)/1.327)
01302 rzLims = MatBounds(193, 264, anApex+17., anApex+17. + ecShift, atan(1./1.327), atan(1./1.327));
01303
01304 else if ( lZ < 517 + ecShift ) rzLims = MatBounds(193, 264, anApex+17. + ecShift, 517 + ecShift, atan(1./1.327), 0);
01305 else if (lZ < 548 + ecShift){
01306 if (lR < 246 ) rzLims = MatBounds(193, 246, 517 + ecShift, 548 + ecShift);
01307 else rzLims = MatBounds(246, 264, 517 + ecShift, 548 + ecShift);
01308 }
01309 else rzLims = MatBounds(193, 264, 548 + ecShift, 554 + ecShift);
01310 }
01311 else if ( lR < 275){
01312 if (lZ < 433) rzLims = MatBounds(264, 275, 0, 433);
01313 else if (lZ < 554 ) rzLims = MatBounds(264, 275, 433, 554);
01314 else rzLims = MatBounds(264, 275, 554, 554 + ecShift);
01315 }
01316 else {
01317 if (lZ < 402) rzLims = MatBounds(275, 287, 0, 402);
01318 else if (lZ < 554) rzLims = MatBounds(275, 287, 402, 554);
01319 else rzLims = MatBounds(275, 287, 554, 554 + ecShift);
01320 }
01321
01322 if ((lZ < 433 || lR < 264) && (lZ < 402 || lR < 275) && (lZ < 517 + ecShift || lR < 246)
01323
01324 && lZ < 548 + ecShift
01325 && ! (lZ < 389 + ecShift && lZ > 335 && lR < 193 )
01326 && ! (lZ > 307 && lZ < 335 && lR < 193 && ((lZ - 307) > (lR - 177.)*1.739))
01327 && ! (lR < 177 && lZ < 398 + ecShift)
01328 && ! (lR < 264 && lR > 193 && fabs(441.5+0.5*ecShift - lZ + (lR - 269.)/1.327) < (8.5 + ecShift*0.5)) )
01329 { dEdx = dEdX_HCal; radX0 = radX0_HCal;
01330 }
01331 else if( (lR < 193 && lZ > 389 && lZ < 389 + ecShift ) || (lR > 264 && lR < 287 && lZ > 554 && lZ < 554 + ecShift)
01332 ||(lR < 264 && lR > 193 && fabs(441.5+8.5+0.5*ecShift - lZ + (lR - 269.)/1.327) < ecShift*0.5) ) {
01333 dEdx = dEdX_Air; radX0 = radX0_Air;
01334 }
01335 else {dEdx = dEdX_HCal*0.05; radX0 = radX0_Air; }
01336 }
01337
01338 else if (lZ < 564 + ecShift){
01339 if (lR < 251) {
01340 rzLims = MatBounds(129, 251, 554 + ecShift, 564 + ecShift);
01341 dEdx = dEdX_Fe; radX0 = radX0_Fe;
01342 }
01343 else {
01344 rzLims = MatBounds(251, 287, 554 + ecShift, 564 + ecShift);
01345 dEdx = dEdX_MCh; radX0 = radX0_MCh;
01346 }
01347 }
01348 else if (lZ < 625 + ecShift){
01349 rzLims = MatBounds(129, 287, 564 + ecShift, 625 + ecShift);
01350 dEdx = dEdX_MCh; radX0 = radX0_MCh;
01351 }
01352 else if (lZ < 785 + ecShift){
01353 if (lR < 275) rzLims = MatBounds(129, 275, 625 + ecShift, 785 + ecShift);
01354 else {
01355 if (lZ < 720 + ecShift) rzLims = MatBounds(275, 287, 625 + ecShift, 720 + ecShift);
01356 else rzLims = MatBounds(275, 287, 720 + ecShift, 785 + ecShift);
01357 }
01358 if (! (lR > 275 && lZ < 720 + ecShift)) { dEdx = dEdX_Fe; radX0 = radX0_Fe; }
01359 else { dEdx = dEdX_MCh; radX0 = radX0_MCh; }
01360 }
01361 else if (lZ < 850 + ecShift){
01362 rzLims = MatBounds(129, 287, 785 + ecShift, 850 + ecShift);
01363 dEdx = dEdX_MCh; radX0 = radX0_MCh;
01364 }
01365 else if (lZ < 910 + ecShift){
01366 rzLims = MatBounds(129, 287, 850 + ecShift, 910 + ecShift);
01367 dEdx = dEdX_Fe; radX0 = radX0_Fe;
01368 }
01369 else if (lZ < 975 + ecShift){
01370 rzLims = MatBounds(129, 287, 910 + ecShift, 975 + ecShift);
01371 dEdx = dEdX_MCh; radX0 = radX0_MCh;
01372 }
01373 else if (lZ < 1000 + ecShift){
01374 rzLims = MatBounds(129, 287, 975 + ecShift, 1000 + ecShift);
01375 dEdx = dEdX_Fe; radX0 = radX0_Fe;
01376 }
01377 else if (lZ < 1063 + ecShift){
01378 rzLims = MatBounds(129, 287, 1000 + ecShift, 1063 + ecShift);
01379 dEdx = dEdX_MCh; radX0 = radX0_MCh;
01380 }
01381 else if ( lZ < 1073 + ecShift){
01382 rzLims = MatBounds(129, 287, 1063 + ecShift, 1073 + ecShift);
01383 dEdx = dEdX_Fe; radX0 = radX0_Fe;
01384 }
01385 else if (lZ < 1E4 ) {
01386 rzLims = MatBounds(129, 287, 1073 + ecShift, 1E4);
01387 dEdx = dEdX_Air; radX0 = radX0_Air;
01388 }
01389 else {
01390
01391 dEdx = dEdX_Air; radX0 = radX0_Air;
01392 }
01393 }
01394 else if (lR <380 && lZ < 667){
01395 if (lZ < 630){
01396 if (lR < 315) rzLims = MatBounds(287, 315, 0, 630);
01397 else if (lR < 341 ) rzLims = MatBounds(315, 341, 0, 630);
01398 else rzLims = MatBounds(341, 380, 0, 630);
01399 } else rzLims = MatBounds(287, 380, 630, 667);
01400
01401 if (lZ < 630) { dEdx = dEdX_coil; radX0 = radX0_coil; }
01402 else {dEdx = dEdX_Air; radX0 = radX0_Air; }
01403 }
01404 else {
01405 if (lZ < 667) {
01406 if (lR < 850){
01407 bool isIron = false;
01408
01409 if (useIsYokeFlag_ && useMagVolumes_ && sv.magVol != 0){
01410 isIron = sv.isYokeVol;
01411 } else {
01412 double bMag = sv.bf.mag();
01413 isIron = (bMag > 0.75 && ! (lZ > 500 && lR <500 && bMag < 1.15)
01414 && ! (lZ < 450 && lR > 420 && bMag < 1.15 ) );
01415 }
01416
01417 rzLims = MatBounds(380, 850, 0, 667);
01418 if (isIron) { dEdx = dEdX_Fe; radX0 = radX0_Fe; }
01419 else { dEdx = dEdX_MCh; radX0 = radX0_MCh; }
01420 } else {
01421 rzLims = MatBounds(850, 1E4, 0, 667);
01422 dEdx = dEdX_Air; radX0 = radX0_Air;
01423 }
01424 }
01425 else if (lR > 750 ){
01426 rzLims = MatBounds(750, 1E4, 667, 1E4);
01427 dEdx = dEdX_Air; radX0 = radX0_Air;
01428 }
01429 else if (lZ < 667 + ecShift){
01430 rzLims = MatBounds(287, 750, 667, 667 + ecShift);
01431 dEdx = dEdX_Air; radX0 = radX0_Air;
01432 }
01433
01434 else if (lZ < 724 + ecShift){
01435 if (lR < 380 ) rzLims = MatBounds(287, 380, 667 + ecShift, 724 + ecShift);
01436 else rzLims = MatBounds(380, 750, 667 + ecShift, 724 + ecShift);
01437 dEdx = dEdX_MCh; radX0 = radX0_MCh;
01438 }
01439 else if (lZ < 785 + ecShift){
01440 if (lR < 380 ) rzLims = MatBounds(287, 380, 724 + ecShift, 785 + ecShift);
01441 else rzLims = MatBounds(380, 750, 724 + ecShift, 785 + ecShift);
01442 dEdx = dEdX_Fe; radX0 = radX0_Fe;
01443 }
01444 else if (lZ < 850 + ecShift){
01445 rzLims = MatBounds(287, 750, 785 + ecShift, 850 + ecShift);
01446 dEdx = dEdX_MCh; radX0 = radX0_MCh;
01447 }
01448 else if (lZ < 910 + ecShift){
01449 rzLims = MatBounds(287, 750, 850 + ecShift, 910 + ecShift);
01450 dEdx = dEdX_Fe; radX0 = radX0_Fe;
01451 }
01452 else if (lZ < 975 + ecShift){
01453 rzLims = MatBounds(287, 750, 910 + ecShift, 975 + ecShift);
01454 dEdx = dEdX_MCh; radX0 = radX0_MCh;
01455 }
01456 else if (lZ < 1000 + ecShift){
01457 rzLims = MatBounds(287, 750, 975 + ecShift, 1000 + ecShift);
01458 dEdx = dEdX_Fe; radX0 = radX0_Fe;
01459 }
01460 else if (lZ < 1063 + ecShift){
01461 if (lR < 360){
01462 rzLims = MatBounds(287, 360, 1000 + ecShift, 1063 + ecShift);
01463 dEdx = dEdX_MCh; radX0 = radX0_MCh;
01464 }
01465
01466 else {
01467 rzLims = MatBounds(360, 750, 1000 + ecShift, 1063 + ecShift);
01468 dEdx = dEdX_Air; radX0 = radX0_Air;
01469 }
01470 }
01471 else if ( lZ < 1073 + ecShift){
01472 rzLims = MatBounds(287, 750, 1063 + ecShift, 1073 + ecShift);
01473
01474 dEdx = dEdX_Air; radX0 = radX0_Air;
01475 }
01476 else if (lZ < 1E4 ) {
01477 rzLims = MatBounds(287, 750, 1073 + ecShift, 1E4);
01478 dEdx = dEdX_Air; radX0 = radX0_Air;
01479 }
01480 else {dEdx = dEdX_Air; radX0 = radX0_Air; }
01481 }
01482
01483 dEdXPrime = dEdx == 0 ? 0 : -dEdx/dEdX_mat*(0.96/p0 + 0.033 - 0.022*pow(p0, -0.33))*1e-3;
01484
01485 return dEdx;
01486 }
01487
01488
01489 int SteppingHelixPropagator::cIndex_(int ind) const{
01490 int result = ind%MAX_POINTS;
01491 if (ind != 0 && result == 0){
01492 result = MAX_POINTS;
01493 }
01494 return result;
01495 }
01496
01497 SteppingHelixPropagator::Result
01498 SteppingHelixPropagator::refToDest(SteppingHelixPropagator::DestType dest,
01499 const SteppingHelixPropagator::StateInfo& sv,
01500 const double pars[6],
01501 double& dist, double& tanDist,
01502 PropagationDirection& refDirection,
01503 double fastSkipDist) const{
01504 static const std::string metname = "SteppingHelixPropagator";
01505 Result result = SteppingHelixStateInfo::NOT_IMPLEMENTED;
01506 double curZ = sv.r3.z();
01507 double curR = sv.r3.perp();
01508
01509 switch (dest){
01510 case RADIUS_DT:
01511 {
01512 double cosDPhiPR = cos((sv.r3.deltaPhi(sv.p3)));
01513 dist = pars[RADIUS_P] - curR;
01514 refDirection = dist*cosDPhiPR > 0 ?
01515 alongMomentum : oppositeToMomentum;
01516 if (fabs(dist) > fastSkipDist){
01517 result = SteppingHelixStateInfo::INACC;
01518 break;
01519 }
01520 tanDist = dist/sv.p3.perp()*sv.p3.mag();
01521 result = SteppingHelixStateInfo::OK;
01522 }
01523 break;
01524 case Z_DT:
01525 {
01526 dist = pars[Z_P] - curZ;
01527 refDirection = sv.p3.z()*dist > 0. ?
01528 alongMomentum : oppositeToMomentum;
01529 if (fabs(dist) > fastSkipDist){
01530 result = SteppingHelixStateInfo::INACC;
01531 break;
01532 }
01533 tanDist = dist/sv.p3.z()*sv.p3.mag();
01534 result = SteppingHelixStateInfo::OK;
01535 }
01536 break;
01537 case PLANE_DT:
01538 {
01539 Point rPlane(pars[0], pars[1], pars[2]);
01540 Vector nPlane(pars[3], pars[4], pars[5]);
01541
01542 double dRDotN = (sv.r3 - rPlane).dot(nPlane);
01543
01544 dist = fabs(dRDotN);
01545 double p0 = sv.p3.mag();
01546 double tN = sv.p3.dot(nPlane)/p0;
01547 refDirection = tN*dRDotN < 0. ?
01548 alongMomentum : oppositeToMomentum;
01549 if (fabs(dist) > fastSkipDist){
01550 result = SteppingHelixStateInfo::INACC;
01551 break;
01552 }
01553 double b0 = sv.bf.mag();
01554 if (fabs(tN)>1e-24) tanDist = -dRDotN/tN;
01555 if (fabs(tanDist) > 1e4) tanDist = 1e4;
01556 if (b0>1.5e-6){
01557 double kVal = 0.0029979*sv.q/p0*b0;
01558 double aVal = tanDist*kVal;
01559 Vector lVec = sv.bf.cross(sv.p3); lVec *= 1./b0/p0;
01560 double bVal = lVec.dot(nPlane)/tN;
01561 if (fabs(aVal*bVal)< 0.3){
01562 double cVal = - sv.bf.cross(lVec).dot(nPlane)/b0/tN;
01563 double tanDCorr = bVal/2. + (bVal*bVal/2. + cVal/6)*aVal;
01564 tanDCorr *= aVal;
01565
01566 if (debug_) LogTrace(metname)<<tanDist<<" vs "<<tanDist*(1.+tanDCorr)<<" corr "<<tanDist*tanDCorr<<std::endl;
01567 tanDist *= (1.+tanDCorr);
01568 } else {
01569 if (debug_) LogTrace(metname)<<"ABVal "<< fabs(aVal*bVal)
01570 <<" = "<<aVal<<" * "<<bVal<<" too large:: will not converge"<<std::endl;
01571 }
01572 }
01573 result = SteppingHelixStateInfo::OK;
01574 }
01575 break;
01576 case CONE_DT:
01577 {
01578
01579 Point cVertex(pars[0], pars[1], pars[2]);
01580 Vector relV3 = sv.r3 - cVertex;
01581 double theta(pars[3]);
01582 if (cVertex.perp() < 1e-5){
01583 double sinDTheta = sin(theta-relV3.theta());
01584 double cosDTheta = cos(theta-relV3.theta());
01585 bool isInside = sin(theta) > sin(relV3.theta())
01586 && cos(theta)*cos(relV3.theta()) > 0;
01587 dist = isInside || cosDTheta > 0 ?
01588 relV3.mag()*sinDTheta : relV3.mag();
01589 double normPhi = isInside ?
01590 Geom::pi() + relV3.phi() : relV3.phi();
01591 double normTheta = theta > Geom::pi()/2. ?
01592 ( isInside ? 1.5*Geom::pi() - theta : theta - Geom::pi()/2. )
01593 : ( isInside ? Geom::pi()/2. - theta : theta + Geom::pi()/2 );
01594
01595 Vector norm; norm.setRThetaPhi(fabs(dist), normTheta, normPhi);
01596 double sineConeP = sin(theta - sv.p3.theta());
01597
01598 double sinSolid = norm.dot(sv.p3)/fabs(dist)/sv.p3.mag();
01599 tanDist = fabs(sinSolid) > fabs(sineConeP) ? dist/fabs(sinSolid) : dist/fabs(sineConeP);
01600
01601
01602 refDirection = sinSolid > 0 ?
01603 oppositeToMomentum : alongMomentum;
01604 if (debug_){
01605 LogTrace(metname)<<"Cone pars: theta "<<theta
01606 <<" normTheta "<<norm.theta()
01607 <<" p3Theta "<<sv.p3.theta()
01608 <<" sinD: "<< sineConeP
01609 <<" sinSolid "<<sinSolid;
01610 }
01611 if (fabs(dist) > fastSkipDist){
01612 result = SteppingHelixStateInfo::INACC;
01613 break;
01614 }
01615 if (debug_){
01616 LogTrace(metname)<<"refToDest:toCone the point is "
01617 <<(isInside? "in" : "out")<<"side the cone"
01618 <<std::endl;
01619 }
01620 }
01621 result = SteppingHelixStateInfo::OK;
01622 }
01623 break;
01624
01625
01626 case PATHL_DT:
01627 {
01628 double curS = fabs(sv.path());
01629 dist = pars[PATHL_P] - curS;
01630 refDirection = pars[PATHL_P] > 0 ?
01631 alongMomentum : oppositeToMomentum;
01632 if (fabs(dist) > fastSkipDist){
01633 result = SteppingHelixStateInfo::INACC;
01634 break;
01635 }
01636 tanDist = dist;
01637 result = SteppingHelixStateInfo::OK;
01638 }
01639 break;
01640 case POINT_PCA_DT:
01641 {
01642 Point pDest(pars[0], pars[1], pars[2]);
01643 dist = (sv.r3 - pDest).mag()+ 1e-24;
01644 tanDist = (sv.r3.dot(sv.p3) - pDest.dot(sv.p3))/sv.p3.mag();
01645
01646 double b0 = sv.bf.mag();
01647 if (b0>1.5e-6){
01648 double p0 = sv.p3.mag();
01649 double kVal = 0.0029979*sv.q/p0*b0;
01650 double aVal = fabs(dist*kVal);
01651 tanDist *= 1./(1.+ aVal);
01652 if (debug_) LogTrace(metname)<<"corrected by aVal "<<aVal<<" to "<<tanDist;
01653 }
01654 refDirection = tanDist < 0 ?
01655 alongMomentum : oppositeToMomentum;
01656 result = SteppingHelixStateInfo::OK;
01657 }
01658 break;
01659 case LINE_PCA_DT:
01660 {
01661 Point rLine(pars[0], pars[1], pars[2]);
01662 Vector dLine(pars[3], pars[4], pars[5]);
01663 dLine = (dLine - rLine);
01664 dLine *= 1./dLine.mag(); if (debug_) LogTrace(metname)<<"dLine "<<dLine;
01665
01666 Vector dR = sv.r3 - rLine;
01667 Vector dRPerp = dR - dLine*(dR.dot(dLine)); if (debug_) LogTrace(metname)<<"dRperp "<<dRPerp;
01668 dist = dRPerp.mag() + 1e-24;
01669 tanDist = dRPerp.dot(sv.p3)/sv.p3.mag();
01670
01671 double cosAlpha = dLine.dot(sv.p3)/sv.p3.mag();
01672 tanDist *= fabs(1./sqrt(fabs(1.-cosAlpha*cosAlpha)+1e-96));
01673
01674
01675 double b0 = sv.bf.mag();
01676 if (b0>1.5e-6){
01677 double p0 = sv.p3.mag();
01678 double kVal = 0.0029979*sv.q/p0*b0;
01679 double aVal = fabs(dist*kVal);
01680 tanDist *= 1./(1.+ aVal);
01681 if (debug_) LogTrace(metname)<<"corrected by aVal "<<aVal<<" to "<<tanDist;
01682 }
01683 refDirection = tanDist < 0 ?
01684 alongMomentum : oppositeToMomentum;
01685 result = SteppingHelixStateInfo::OK;
01686 }
01687 break;
01688 default:
01689 {
01690
01691 dist = 1e12;
01692 tanDist = 1e12;
01693 refDirection = anyDirection;
01694 result = SteppingHelixStateInfo::NOT_IMPLEMENTED;
01695 }
01696 break;
01697 }
01698
01699 double tanDistConstrained = tanDist;
01700 if (fabs(tanDist/dist) > 4) tanDistConstrained *= fabs(dist/tanDist*4.);
01701
01702 if (debug_){
01703 LogTrace(metname)<<"refToDest input: dest"<<dest<<" pars[]: ";
01704 for (int i = 0; i < 6; i++){
01705 LogTrace(metname)<<", "<<i<<" "<<pars[i];
01706 }
01707 LogTrace(metname)<<std::endl;
01708 LogTrace(metname)<<"refToDest output: "
01709 <<"\t dist" << dist
01710 <<"\t tanDist "<< tanDist
01711 <<"\t tanDistConstr "<< tanDistConstrained
01712 <<"\t refDirection "<< refDirection
01713 <<std::endl;
01714 }
01715 tanDist = tanDistConstrained;
01716
01717 return result;
01718 }
01719
01720 SteppingHelixPropagator::Result
01721 SteppingHelixPropagator::refToMagVolume(const SteppingHelixPropagator::StateInfo& sv,
01722 PropagationDirection dir,
01723 double& dist, double& tanDist,
01724 double fastSkipDist, bool expectNewMagVolume) const{
01725
01726 static const std::string metname = "SteppingHelixPropagator";
01727 Result result = SteppingHelixStateInfo::NOT_IMPLEMENTED;
01728 const MagVolume* cVol = sv.magVol;
01729
01730 if (cVol == 0) return result;
01731 const std::vector<VolumeSide>& cVolFaces(cVol->faces());
01732
01733 double distToFace[6] = {0,0,0,0,0,0};
01734 double tanDistToFace[6] = {0,0,0,0,0,0};
01735 PropagationDirection refDirectionToFace[6];
01736 Result resultToFace[6];
01737 int iFDest = -1;
01738 int iDistMin = -1;
01739
01740 uint iFDestSorted[6] = {0,0,0,0,0,0};
01741 uint nDestSorted =0;
01742 uint nearParallels = 0;
01743
01744 if (debug_){
01745 LogTrace(metname)<<"Trying volume "<<DDSolidShapesName::name(cVol->shapeType())
01746 <<" with "<<cVolFaces.size()<<" faces"<<std::endl;
01747 }
01748
01749 for (uint iFace = 0; iFace < cVolFaces.size(); iFace++){
01750 if (iFace > 5){
01751 LogTrace(metname)<<"Too many faces"<<std::endl;
01752 }
01753 if (debug_){
01754 LogTrace(metname)<<"Start with face "<<iFace<<std::endl;
01755 }
01756
01757
01758
01759 const Surface* cPlane = 0;
01760 const Cylinder* cCyl = 0;
01761 const Cone* cCone = 0;
01762 if (typeid(cVolFaces[iFace].surface()) == typeid(const Plane&)){
01763 cPlane = &cVolFaces[iFace].surface();
01764 } else if (typeid(cVolFaces[iFace].surface()) == typeid(const Cylinder&)){
01765 cCyl = dynamic_cast<const Cylinder*>(&cVolFaces[iFace].surface());
01766 } else if (typeid(cVolFaces[iFace].surface()) == typeid(const Cone&)){
01767 cCone = dynamic_cast<const Cone*>(&cVolFaces[iFace].surface());
01768 } else {
01769 edm::LogWarning(metname)<<"Could not cast a volume side surface to a known type"<<std::endl;
01770 }
01771
01772 if (debug_){
01773 if (cPlane!=0) LogTrace(metname)<<"The face is a plane at "<<cPlane<<std::endl;
01774 if (cCyl!=0) LogTrace(metname)<<"The face is a cylinder at "<<cCyl<<std::endl;
01775 }
01776
01777 double pars[6] = {0,0,0,0,0,0};
01778 DestType dType = UNDEFINED_DT;
01779 if (cPlane != 0){
01780 GlobalPoint rPlane = cPlane->position();
01781
01782 GlobalVector nPlane(cPlane->rotation().zx(), cPlane->rotation().zy(), cPlane->rotation().zz());
01783
01784 if (sv.r3.z() < 0 || !vbField_->isZSymmetric() ){
01785 pars[0] = rPlane.x(); pars[1] = rPlane.y(); pars[2] = rPlane.z();
01786 pars[3] = nPlane.x(); pars[4] = nPlane.y(); pars[5] = nPlane.z();
01787 } else {
01788 pars[0] = rPlane.x(); pars[1] = rPlane.y(); pars[2] = -rPlane.z();
01789 pars[3] = nPlane.x(); pars[4] = nPlane.y(); pars[5] = -nPlane.z();
01790 }
01791 dType = PLANE_DT;
01792 } else if (cCyl != 0){
01793 if (debug_){
01794 LogTrace(metname)<<"Cylinder at "<<cCyl->position()
01795 <<" rorated by "<<cCyl->rotation()
01796 <<std::endl;
01797 }
01798 pars[RADIUS_P] = cCyl->radius();
01799 dType = RADIUS_DT;
01800 } else if (cCone != 0){
01801 if (debug_){
01802 LogTrace(metname)<<"Cone at "<<cCone->position()
01803 <<" rorated by "<<cCone->rotation()
01804 <<" vertex at "<<cCone->vertex()
01805 <<" angle of "<<cCone->openingAngle()
01806 <<std::endl;
01807 }
01808 if (sv.r3.z() < 0 || !vbField_->isZSymmetric()){
01809 pars[0] = cCone->vertex().x(); pars[1] = cCone->vertex().y();
01810 pars[2] = cCone->vertex().z();
01811 pars[3] = cCone->openingAngle();
01812 } else {
01813 pars[0] = cCone->vertex().x(); pars[1] = cCone->vertex().y();
01814 pars[2] = -cCone->vertex().z();
01815 pars[3] = Geom::pi() - cCone->openingAngle();
01816 }
01817 dType = CONE_DT;
01818 } else {
01819 LogTrace(metname)<<"Unknown surface"<<std::endl;
01820 resultToFace[iFace] = SteppingHelixStateInfo::UNDEFINED;
01821 continue;
01822 }
01823 resultToFace[iFace] =
01824 refToDest(dType, sv, pars,
01825 distToFace[iFace], tanDistToFace[iFace], refDirectionToFace[iFace], fastSkipDist);
01826
01827
01828 if (resultToFace[iFace] != SteppingHelixStateInfo::OK){
01829 if (resultToFace[iFace] == SteppingHelixStateInfo::INACC) result = SteppingHelixStateInfo::INACC;
01830 }
01831
01832
01833
01834
01835 if (resultToFace[iFace] == SteppingHelixStateInfo::OK){
01836 bool isNearParallel = fabs(distToFace[iFace]/tanDistToFace[iFace]/tanDistToFace[iFace]) < 0.1/sv.p3.mag()
01837 && fabs(distToFace[iFace]/tanDistToFace[iFace]) < 0.05;
01838 if (refDirectionToFace[iFace] == dir || isNearParallel){
01839 if (isNearParallel) nearParallels++;
01840 iFDestSorted[nDestSorted] = iFace;
01841 nDestSorted++;
01842 }
01843 }
01844
01845
01846 if (refDirectionToFace[iFace] == dir){
01847 if (iDistMin == -1) iDistMin = iFace;
01848 else if (fabs(distToFace[iFace]) < fabs(distToFace[iDistMin])) iDistMin = iFace;
01849 }
01850 if (debug_)
01851 LogTrace(metname)<<cVol<<" "<<iFace<<" "
01852 <<tanDistToFace[iFace]<<" "<<distToFace[iFace]<<" "<<refDirectionToFace[iFace]<<" "<<dir<<std::endl;
01853
01854 }
01855
01856 for (uint i = 0;i<nDestSorted; ++i){
01857 uint iMax = nDestSorted-i-1;
01858 for (uint j=0;j<nDestSorted-i; ++j){
01859 if (fabs(tanDistToFace[iFDestSorted[j]]) > fabs(tanDistToFace[iFDestSorted[iMax]]) ){
01860 iMax = j;
01861 }
01862 }
01863 uint iTmp = iFDestSorted[nDestSorted-i-1];
01864 iFDestSorted[nDestSorted-i-1] = iFDestSorted[iMax];
01865 iFDestSorted[iMax] = iTmp;
01866 }
01867
01868 if (debug_){
01869 for (uint i=0;i<nDestSorted;++i){
01870 LogTrace(metname)<<cVol<<" "<<i<<" "<<iFDestSorted[i]<<" "<<tanDistToFace[iFDestSorted[i]]<<std::endl;
01871 }
01872 }
01873
01874
01875
01876 for (uint i=0; i<nDestSorted;++i){
01877 iFDest = iFDestSorted[i];
01878
01879 double sign = dir == alongMomentum ? 1. : -1.;
01880 Point gPointEst(sv.r3);
01881 Vector lDelta(sv.p3); lDelta *= 1./sv.p3.mag()*sign*fabs(distToFace[iFDest]);
01882 gPointEst += lDelta;
01883 if (debug_){
01884 LogTrace(metname)<<"Linear est point "<<gPointEst
01885 <<" for iFace "<<iFDest<<std::endl;
01886 }
01887 GlobalPoint gPointEstNegZ(gPointEst.x(), gPointEst.y(), -fabs(gPointEst.z()));
01888 GlobalPoint gPointEstNorZ(gPointEst.x(), gPointEst.y(), gPointEst.z() );
01889 if ( (vbField_->isZSymmetric() && cVol->inside(gPointEstNegZ))
01890 || ( !vbField_->isZSymmetric() && cVol->inside(gPointEstNorZ) ) ){
01891 if (debug_){
01892 LogTrace(metname)<<"The point is inside the volume"<<std::endl;
01893 }
01894
01895 result = SteppingHelixStateInfo::OK;
01896 dist = distToFace[iFDest];
01897 tanDist = tanDistToFace[iFDest];
01898 if (debug_){
01899 LogTrace(metname)<<"Got a point near closest boundary -- face "<<iFDest<<std::endl;
01900 }
01901 break;
01902 }
01903 }
01904
01905 if (result != SteppingHelixStateInfo::OK && expectNewMagVolume){
01906 double sign = dir == alongMomentum ? 1. : -1.;
01907
01908
01909 if (nDestSorted-nearParallels > 0 ) result = SteppingHelixStateInfo::WRONG_VOLUME;
01910 else {
01911
01912 Point gPointEst(sv.r3);
01913 double lDist = fabs(distToFace[iDistMin]);
01914 if (lDist > fastSkipDist) lDist = fastSkipDist;
01915 Vector lDelta(sv.p3); lDelta *= 1./sv.p3.mag()*sign*lDist;
01916 gPointEst += lDelta;
01917 if (debug_){
01918 LogTrace(metname)<<"Linear est point to shortest dist "<<gPointEst
01919 <<" for iFace "<<iDistMin<<" at distance "<<lDist*sign<<std::endl;
01920 }
01921 GlobalPoint gPointEstNegZ(gPointEst.x(), gPointEst.y(), -fabs(gPointEst.z()));
01922 GlobalPoint gPointEstNorZ(gPointEst.x(), gPointEst.y(), gPointEst.z() );
01923 if ( (vbField_->isZSymmetric() && cVol->inside(gPointEstNegZ))
01924 || ( !vbField_->isZSymmetric() && cVol->inside(gPointEstNorZ) ) ){
01925 if (debug_){
01926 LogTrace(metname)<<"The point is inside the volume"<<std::endl;
01927 }
01928
01929 }else {
01930 result = SteppingHelixStateInfo::WRONG_VOLUME;
01931 }
01932 }
01933
01934 if (result == SteppingHelixStateInfo::WRONG_VOLUME){
01935 dist = sign*0.05;
01936 tanDist = dist*1.01;
01937 if( debug_){
01938 LogTrace(metname)<<"Wrong volume located: return small dist, tandist"<<std::endl;
01939 }
01940 }
01941 }
01942
01943 if (result == SteppingHelixStateInfo::INACC){
01944 if (debug_) LogTrace(metname)<<"All faces are too far"<<std::endl;
01945 } else if (result == SteppingHelixStateInfo::WRONG_VOLUME){
01946 if (debug_) LogTrace(metname)<<"Appear to be in a wrong volume"<<std::endl;
01947 } else if (result != SteppingHelixStateInfo::OK){
01948 if (debug_) LogTrace(metname)<<"Something else went wrong"<<std::endl;
01949 }
01950
01951
01952 return result;
01953 }
01954
01955
01956 SteppingHelixPropagator::Result
01957 SteppingHelixPropagator::refToMatVolume(const SteppingHelixPropagator::StateInfo& sv,
01958 PropagationDirection dir,
01959 double& dist, double& tanDist,
01960 double fastSkipDist) const{
01961
01962 static const std::string metname = "SteppingHelixPropagator";
01963 Result result = SteppingHelixStateInfo::NOT_IMPLEMENTED;
01964
01965 double parLim[6] = {sv.rzLims.rMin, sv.rzLims.rMax,
01966 sv.rzLims.zMin, sv.rzLims.zMax,
01967 sv.rzLims.th1, sv.rzLims.th2 };
01968
01969 double distToFace[4] = {0,0,0,0};
01970 double tanDistToFace[4] = {0,0,0,0};
01971 PropagationDirection refDirectionToFace[4];
01972 Result resultToFace[4];
01973 int iFDest = -1;
01974
01975 for (uint iFace = 0; iFace < 4; iFace++){
01976 if (debug_){
01977 LogTrace(metname)<<"Start with mat face "<<iFace<<std::endl;
01978 }
01979
01980 double pars[6] = {0,0,0,0,0,0};
01981 DestType dType = UNDEFINED_DT;
01982 if (iFace > 1){
01983 if (fabs(parLim[iFace+2])< 1e-6){
01984 if (sv.r3.z() < 0){
01985 pars[0] = 0; pars[1] = 0; pars[2] = -parLim[iFace];
01986 pars[3] = 0; pars[4] = 0; pars[5] = 1;
01987 } else {
01988 pars[0] = 0; pars[1] = 0; pars[2] = parLim[iFace];
01989 pars[3] = 0; pars[4] = 0; pars[5] = 1;
01990 }
01991 dType = PLANE_DT;
01992 } else {
01993 if (sv.r3.z() > 0){
01994 pars[0] = 0; pars[1] = 0;
01995 pars[2] = parLim[iFace];
01996 pars[3] = Geom::pi()/2. - parLim[iFace+2];
01997 } else {
01998 pars[0] = 0; pars[1] = 0;
01999 pars[2] = - parLim[iFace];
02000 pars[3] = Geom::pi()/2. + parLim[iFace+2];
02001 }
02002 dType = CONE_DT;
02003 }
02004 } else {
02005 pars[RADIUS_P] = parLim[iFace];
02006 dType = RADIUS_DT;
02007 }
02008
02009 resultToFace[iFace] =
02010 refToDest(dType, sv, pars,
02011 distToFace[iFace], tanDistToFace[iFace], refDirectionToFace[iFace], fastSkipDist);
02012
02013 if (resultToFace[iFace] != SteppingHelixStateInfo::OK){
02014 if (resultToFace[iFace] == SteppingHelixStateInfo::INACC) result = SteppingHelixStateInfo::INACC;
02015 continue;
02016 }
02017 if (refDirectionToFace[iFace] == dir || fabs(distToFace[iFace]/tanDistToFace[iFace]) < 2e-2){
02018 double sign = dir == alongMomentum ? 1. : -1.;
02019 Point gPointEst(sv.r3);
02020 Vector lDelta(sv.p3); lDelta *= sign*fabs(distToFace[iFace])/sv.p3.mag();
02021 gPointEst += lDelta;
02022 if (debug_){
02023 LogTrace(metname)<<"Linear est point "<<gPointEst
02024 <<std::endl;
02025 }
02026 double lZ = fabs(gPointEst.z());
02027 double lR = gPointEst.perp();
02028 if ( (lZ - parLim[2]) > lR*tan(parLim[4])
02029 && (lZ - parLim[3]) < lR*tan(parLim[5])
02030 && lR > parLim[0] && lR < parLim[1]){
02031 if (debug_){
02032 LogTrace(metname)<<"The point is inside the volume"<<std::endl;
02033 }
02034
02035 if (iFDest == -1){
02036 iFDest = iFace;
02037 } else {
02038 if (fabs(tanDistToFace[iFDest]) > fabs(tanDistToFace[iFace])){
02039 iFDest = iFace;
02040 }
02041 }
02042 } else {
02043 if (debug_){
02044 LogTrace(metname)<<"The point is NOT inside the volume"<<std::endl;
02045 }
02046 }
02047 }
02048
02049 }
02050 if (iFDest != -1){
02051 result = SteppingHelixStateInfo::OK;
02052 dist = distToFace[iFDest];
02053 tanDist = tanDistToFace[iFDest];
02054 if (debug_){
02055 LogTrace(metname)<<"Got a point near closest boundary -- face "<<iFDest<<std::endl;
02056 }
02057 } else {
02058 if (debug_){
02059 LogTrace(metname)<<"Failed to find a dest point inside the volume"<<std::endl;
02060 }
02061 }
02062
02063 return result;
02064 }
02065
02066
02067 bool SteppingHelixPropagator::isYokeVolume(const MagVolume* vol) const {
02068 static const std::string metname = "SteppingHelixPropagator";
02069 if (vol == 0) return false;
02070 const MFGrid* mGrid = reinterpret_cast<const MFGrid*>(vol->provider());
02071 std::vector<int> dims(mGrid->dimensions());
02072
02073 LocalVector lVCen(mGrid->nodeValue(dims[0]/2, dims[1]/2, dims[2]/2));
02074 LocalVector lVZLeft(mGrid->nodeValue(dims[0]/2, dims[1]/2, dims[2]/5));
02075 LocalVector lVZRight(mGrid->nodeValue(dims[0]/2, dims[1]/2, (dims[2]*4)/5));
02076
02077 double mag2VCen = lVCen.mag2();
02078 double mag2VZLeft = lVZLeft.mag2();
02079 double mag2VZRight = lVZRight.mag2();
02080
02081 bool result = false;
02082 if (mag2VCen > 0.6 && mag2VZLeft > 0.6 && mag2VZRight > 0.6){
02083 if (debug_) LogTrace(metname)<<"Volume is magnetic, located at "<<vol->position()<<std::endl;
02084 result = true;
02085 } else {
02086 if (debug_) LogTrace(metname)<<"Volume is not magnetic, located at "<<vol->position()<<std::endl;
02087 }
02088
02089 return result;
02090 }