00001
00002
00003
00004 #include "gsl/gsl_math.h"
00005
00006
00007 #include "GaudiKernel/ToolFactory.h"
00008
00009
00010 #include "DetDesc/ITransportSvc.h"
00011 #include "DetDesc/Material.h"
00012
00013 #include "Event/TrackParameters.h"
00014
00015
00016 #include "TrackFirstCleverExtrapolator.h"
00017
00018
00019 #include "gsl/gsl_math.h"
00020
00021
00022 static const ToolFactory<TrackFirstCleverExtrapolator> s_factory;
00023 const IToolFactory& TrackFirstCleverExtrapolatorFactory = s_factory;
00024
00038 TrackFirstCleverExtrapolator::TrackFirstCleverExtrapolator
00039 (const std::string& type, const std::string& name, const IInterface* parent):
00040 TrackExtrapolator(type, name, parent),
00041 m_tMax(10.),
00042 m_eMax(100.0*MeV),
00043 m_freeFieldExtrapolator(0),
00044 m_shortFieldExtrapolator(0),
00045 m_longFieldExtrapolator(0)
00046 {
00047 declareInterface<ITrackExtrapolator>( this );
00048
00049
00050 declareProperty("fieldStart" , m_zFieldStart = -500.*mm);
00051 declareProperty("fieldStop" , m_zFieldStop= 21000.*mm );
00052 declareProperty("shortDist" , m_shortDist = 100.*mm);
00053 declareProperty("freeFieldExtrapolatorName",
00054 m_freeFieldExtrapolatorName = "TrLinearExtrapolator");
00055 declareProperty("shortFieldExtrapolatorName",
00056 m_shortFieldExtrapolatorName ="TrParabolicExtrapolator");
00057 declareProperty("longFieldExtrapolatorName",
00058 m_longFieldExtrapolatorName = "TrHerabExtrapolator");
00059 declareProperty("applyMultScattCorr" , m_applyMultScattCorr = true);
00060 declareProperty("fms2" , m_fms2 = 1.0);
00061 declareProperty("thickWall" , m_thickWall = 0.*mm);
00062 declareProperty("applyEnergyLossCorr" , m_applyEnergyLossCorr = true);
00063 declareProperty("energyLoss" ,
00064 m_energyLoss = 354.1 * MeV*mm2/mole );
00065 declareProperty("maxStepSize" , m_maxStepSize = 1000. * mm );
00066 declareProperty("minRadThreshold" , m_minRadThreshold = 1.0e-4 );
00067
00068
00069 declareProperty("applyElectronEnergyLossCorr",
00070 m_applyElectronEnergyLossCorr = true);
00071 declareProperty("startElectronCorr",
00072 m_startElectronCorr = 2500.*mm);
00073 declareProperty("stopElectronCorr",
00074 m_stopElectronCorr = 9000.*mm);
00075
00076
00077
00078
00079 }
00080
00081
00082 TrackFirstCleverExtrapolator::~TrackFirstCleverExtrapolator()
00083 {
00084 }
00085
00086
00087 StatusCode TrackFirstCleverExtrapolator::initialize()
00088 {
00089
00090
00091 StatusCode sc = GaudiTool::initialize();
00092 if (sc.isFailure()){
00093 return Error("Failed to initialize", sc);
00094 }
00095
00096
00097 m_freeFieldExtrapolator=tool<ITrackExtrapolator>(m_freeFieldExtrapolatorName);
00098
00099
00100 m_shortFieldExtrapolator=tool<ITrackExtrapolator>(m_shortFieldExtrapolatorName);
00101
00102
00103 m_longFieldExtrapolator=tool<ITrackExtrapolator>(m_longFieldExtrapolatorName);
00104
00105
00106 m_transportSvc = svc<ITransportSvc>( "TransportSvc",true);
00107
00108 return StatusCode::SUCCESS;
00109 }
00110
00111
00112
00113
00114 StatusCode TrackFirstCleverExtrapolator::propagate( State& state,
00115 double zNew,
00116 ParticleID partId) {
00117
00118 StatusCode sc;
00119
00120 size_t ndim = state.nParameters();
00121
00122
00123 m_F = HepMatrix(ndim, ndim, 1);
00124
00125
00126 double zStart = state.z();
00127 if (fabs(zNew-zStart) < TrackParameters::hiTolerance) {
00128
00129 debug() << "already at required z position" << endreq;
00130 return StatusCode::SUCCESS;
00131 }
00132
00133
00134 if (zStart>zNew) {
00135 m_upStream = true;
00136 } else{
00137 m_upStream = false;
00138 }
00139
00140 int nbStep = (int)( fabs( zNew-zStart ) / m_maxStepSize ) + 1;
00141 double zStep = ( zNew - zStart ) / nbStep;
00142 int nWall;
00143 double maxSlope = 5.;
00144 double maxTransverse = 10 * m;
00145
00146 for ( int step=0 ; nbStep > step ; ++step ) {
00147
00148 ILVolume::Intersections intersept;
00149 HepVector& tX = state.state();
00150 HepPoint3D start( tX[0], tX[1], state.z() );
00151 HepVector3D vect( tX[2]*zStep, tX[3]*zStep, zStep );
00152
00153
00154
00155 if ( fabs(tX[0]) > maxTransverse ) {
00156 double pos = GSL_SIGN(tX[0])* maxTransverse ;
00157 warning() << "Protect against absurd tracks: X "
00158 << state.x() << " set to " << pos << ", abort. " << endreq;
00159 state.setX(pos);
00160 return StatusCode::FAILURE;
00161 }
00162
00163 if ( fabs(tX[1]) > maxTransverse ) {
00164 double pos = GSL_SIGN(tX[1])*maxTransverse;
00165 warning() << "Protect against absurd tracks: Y "
00166 << state.y() << " set to " << pos << ", abort. " << endreq;
00167 state.setY(pos);
00168 return StatusCode::FAILURE;
00169 }
00170
00171 if (fabs(state.tx()) > maxSlope){
00172 double slopeX = GSL_SIGN(state.tx())* maxSlope;
00173 warning() << "Protect against looping tracks: Tx "
00174 << state.tx() << " set to " << slopeX << ", abort. " << endreq;
00175 state.setTx(slopeX);
00176 return StatusCode::FAILURE;
00177 }
00178
00179 if (fabs(state.ty()) > maxSlope){
00180 double slopeY = GSL_SIGN(state.ty())*maxSlope;
00181 warning() << "Protect against looping tracks: Ty "
00182 << state.ty() << " set to " << slopeY << ", abort. " << endreq;
00183 state.setTy(slopeY);
00184 return StatusCode::FAILURE;
00185 }
00186
00187
00188 if ( (7.0*mm > fabs(zStep)) && (5000.0*mm < start.z() ) ) {
00189 nWall = 0;
00190 debug() << "No transport between z= " << start.z() << " and "
00191 << start.z() + vect.z() << endreq;
00192 }
00193
00194 else if (fabs(start.x()) > 25.*m || fabs(start.y()) > 25.*m ||
00195 fabs(start.z()) > 25.*m ||
00196 fabs(start.x()+vect.x()) > 25.*m ||
00197 fabs(start.y()+vect.y()) > 25.*m ||
00198 fabs(start.z()+vect.z()) > 25.*m ) {
00199 nWall = 0;
00200 debug() << "No transport between z= " << start.z() << " and "
00201 << start.z() + vect.z()
00202 << ", since it reaches outside LHCb" << endreq;
00203 }
00204 else {
00205
00206 nWall = m_transportSvc->intersections( start, vect, 0., 1.,
00207 intersept, m_minRadThreshold );
00208
00209
00210
00211
00212 if (msgLevel(MSG::DEBUG)) {
00213 debug() << "Transport : " << nWall
00214 << " intersepts between z= " << start.z() << " and "
00215 << start.z() + vect.z() << endreq;
00216
00217
00218 }
00219 }
00220
00221 std::vector<double> zWall;
00222 std::vector<double> tWall;
00223 std::vector<double> radLengthWall;
00224 std::vector<const Material*> matWall;
00225
00226 double t1, t2, dz;
00227 double pos, thick, radl;
00228 for ( int ii = 0 ; nWall > ii ; ++ii ) {
00229 t1 = intersept[ii].first.first * zStep;
00230 t2 = intersept[ii].first.second * zStep;
00231 dz = zScatter(t1,t2);
00232 pos = start.z() + dz;
00233 thick = fabs( t2 - t1 );
00234 radl = thick / intersept[ii].second->radiationLength();
00235 if ( m_minRadThreshold < radl ) {
00236 zWall.push_back( pos );
00237 tWall.push_back( thick);
00238 radLengthWall.push_back( radl );
00239 matWall.push_back( intersept[ii].second );
00240 }
00241
00242 if ((msgLevel(MSG::DEBUG))&& (m_minRadThreshold < radl)){
00243 debug() << format(" %2i x%8.2f y%8.2f z%10.3f thick%8.3f radl%7.3f %%",
00244 ii ,
00245 tX[0] + dz * tX[2],
00246 tX[1] + dz * tX[3],
00247 pos, thick, 100.*radl) <<endreq ;
00248 }
00249 }
00250
00251 zWall.push_back( start.z() + zStep );
00252 radLengthWall.push_back( 0. );
00253 tWall.push_back( 0. );
00254 matWall.push_back( 0);
00255 nWall = tWall.size();
00256
00257
00258 for (int iStep=0; iStep<nWall; ++iStep){
00259
00260
00261 std::list<TrackTransportStep> transStepList;
00262 sc = createTransportSteps( state.z(), zWall[iStep], transStepList );
00263
00264 if (transStepList.empty()){
00265 return Error( "no transport steps !!!!", StatusCode::FAILURE);
00266 }
00267
00268
00269 std::list<TrackTransportStep>::iterator iTransStep = transStepList.begin();
00270 bool stopTransport = false;
00271
00272 while ((iTransStep!=transStepList.end())&&(stopTransport == false)){
00273
00274
00275 ITrackExtrapolator* thisExtrapolator = (*iTransStep).extrapolator();
00276 sc = thisExtrapolator->propagate( state, (*iTransStep).z() );
00277
00278
00279 updateTransportMatrix( thisExtrapolator->transportMatrix() );
00280
00281
00282 if (sc.isFailure()) {
00283 stopTransport = true;
00284 warning() << "Transport to " << (*iTransStep).z()
00285 << "using "+thisExtrapolator->name() << " FAILED" << endreq;
00286 }
00287 ++iTransStep;
00288 }
00289
00290 if (stopTransport == true) return sc;
00291
00292
00293 if (fabs(state.tx()) > maxSlope){
00294 double slopeX = GSL_SIGN( state.tx() )*maxSlope;
00295 warning() << "Protect against looping tracks: Tx "
00296 << state.tx() << " set to " << slopeX << ", abort. " << endreq;
00297 state.setTx(slopeX);
00298 return StatusCode::FAILURE;
00299 }
00300
00301 if (fabs(state.ty()) > maxSlope){
00302 double slopeY = GSL_SIGN(state.ty())*maxSlope;
00303 warning() << "Protect against looping tracks: Ty "
00304 << state.ty() << " set to " << slopeY << ", abort. " << endreq;
00305 state.setTy(slopeY);
00306 return StatusCode::FAILURE;
00307 }
00308
00309
00310 if (m_applyMultScattCorr == true){
00311 if (tWall[iStep] < m_thickWall){
00312 sc = thinScatter( state, radLengthWall[iStep] );
00313 }
00314 else{
00315 sc = thickScatter( state, tWall[iStep], radLengthWall[iStep] );
00316 }
00317 }
00318
00319
00320 if (( m_applyEnergyLossCorr == true)&&(matWall[iStep] != 0)){
00321 sc = energyLoss( state, tWall[iStep], matWall[iStep] );
00322 }
00323
00324
00325 if ((m_applyElectronEnergyLossCorr == true) &&(11 == partId.abspid())){
00326 if ((state.z() > m_startElectronCorr) &&
00327 (state.z() < m_stopElectronCorr)){
00328 sc = electronEnergyLoss(state,radLengthWall[iStep]);
00329 }
00330 }
00331
00332 }
00333 }
00334
00335 verbose() << "TrStateP extrapolated succesfully" << endreq;
00336
00337 return StatusCode::SUCCESS;
00338 }
00339
00340 StatusCode TrackFirstCleverExtrapolator::createTransportSteps
00341 (double zStart,double zTarget, std::list<TrackTransportStep>& transStepList){
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 if ((GSL_MAX(zTarget,zStart) <= m_zFieldStart) ||
00353 (GSL_MIN(zTarget,zStart) >= m_zFieldStop)){
00354 verbose() << "Field free Transport from " << zStart << " to "
00355 << zTarget << endreq;
00356 TrackTransportStep tStep = TrackTransportStep(m_freeFieldExtrapolator,zTarget);
00357 transStepList.push_back(tStep);
00358 }
00359
00360
00361 else if ((GSL_MIN(zTarget,zStart) >= m_zFieldStart) &&
00362 (GSL_MAX(zTarget,zStart) <= m_zFieldStop)){
00363
00364 ITrackExtrapolator* magExtrapolator= chooseMagFieldExtrapolator( zStart,
00365 zTarget);
00366
00367 if (msgLevel(MSG::VERBOSE)) verbose() << "Magnet region Transport from "
00368 << zStart << " to " << zTarget
00369 << " using " <<magExtrapolator->name() << endreq;
00370
00371 TrackTransportStep tStep = TrackTransportStep( magExtrapolator, zTarget);
00372 transStepList.push_back(tStep);
00373 }
00374
00375
00376 else if ((GSL_MIN(zTarget,zStart) < m_zFieldStart) &&
00377 (GSL_MAX(zTarget,zStart) <= m_zFieldStop)){
00378
00379 verbose()
00380 << "Transporting from inside to outside - crossing m_zFieldStart"
00381 << endreq;
00382
00383 if ( zTarget < m_zFieldStart ){
00384
00385 ITrackExtrapolator* magExtrapolator =
00386 chooseMagFieldExtrapolator(zStart,m_zFieldStart);
00387
00388 verbose()
00389 << "Magnet region Transport from " << zStart << " to "
00390 << m_zFieldStart
00391 << " using " << magExtrapolator->name() << endreq;
00392 TrackTransportStep tStep1 = TrackTransportStep(magExtrapolator,m_zFieldStart);
00393 transStepList.push_back(tStep1);
00394
00395 verbose() << "Field free Transport from " << m_zFieldStart
00396 << " to " << zTarget << endreq;
00397 TrackTransportStep tStep2 = TrackTransportStep(m_freeFieldExtrapolator,zTarget);
00398 transStepList.push_back(tStep2);
00399 } else {
00400
00401 verbose() << "Field free Transport from " << zStart << " to "
00402 << m_zFieldStart << endreq;
00403 TrackTransportStep tStep1 = TrackTransportStep(m_freeFieldExtrapolator,
00404 m_zFieldStart);
00405 transStepList.push_back(tStep1);
00406
00407 ITrackExtrapolator* magExtrapolator = chooseMagFieldExtrapolator(
00408 m_zFieldStart,
00409 zTarget);
00410
00411 verbose() << "Magnet region Transport from " << m_zFieldStart
00412 << " to " << zTarget
00413 << " using " <<magExtrapolator->name() << endreq;
00414 TrackTransportStep tStep2 = TrackTransportStep(magExtrapolator,zTarget);
00415 transStepList.push_back(tStep2);
00416 }
00417 }
00418
00419
00420
00421 else if ((GSL_MIN(zTarget,zStart) >= m_zFieldStart) &&
00422 (GSL_MAX(zTarget,zStart) > m_zFieldStop)){
00423
00424 verbose()
00425 << "Transporting from inside to outside - crossing m_zFieldStop"
00426 << endreq;
00427
00428 if (zTarget>m_zFieldStop){
00429
00430 ITrackExtrapolator* magExtrapolator = chooseMagFieldExtrapolator(zStart,
00431 m_zFieldStop);
00432
00433 if (msgLevel(MSG::VERBOSE)) verbose()
00434 << "Magnet region Transport from " << zStart << " to " << m_zFieldStop
00435 << " using " << magExtrapolator->name() << endreq;
00436 TrackTransportStep tStep1 = TrackTransportStep(magExtrapolator,m_zFieldStop);
00437 transStepList.push_back(tStep1);
00438
00439 verbose() << "Field free Transport from " << zStart << " to "
00440 << zTarget << endreq;
00441 TrackTransportStep tStep2 = TrackTransportStep(m_freeFieldExtrapolator,zTarget);
00442 transStepList.push_back(tStep2);
00443
00444 }
00445 else{
00446
00447 verbose() << "Field free Transport from " << zStart << " to "
00448 << m_zFieldStop << endreq;
00449 TrackTransportStep tStep1 = TrackTransportStep(m_freeFieldExtrapolator,
00450 m_zFieldStop);
00451 transStepList.push_back(tStep1);
00452
00453 ITrackExtrapolator* magExtrapolator = chooseMagFieldExtrapolator(
00454 m_zFieldStop,
00455 zTarget);
00456
00457 if (msgLevel(MSG::VERBOSE)) verbose()
00458 << "Magnet region Transport from " << zStart << " to " << zTarget
00459 << " using "<< magExtrapolator->name() << endreq;
00460 TrackTransportStep tStep2 = TrackTransportStep(magExtrapolator,zTarget);
00461 transStepList.push_back(tStep2);
00462 }
00463 }
00464
00465
00466
00467 else if ((GSL_MAX(zTarget,zStart) > m_zFieldStop) &&
00468 (GSL_MIN(zTarget,zStart) < m_zFieldStart)){
00469 verbose() << "Transport from outside magnet to outside magnet"
00470 << endreq;
00471
00472
00473 double z1 =0.;
00474 double z2 =0.;
00475 if ( zTarget < zStart ){
00476
00477 z1 = m_zFieldStop;
00478 z2 = m_zFieldStart;
00479 }
00480 else{
00481
00482 z1 = m_zFieldStart;
00483 z2 = m_zFieldStop;
00484 }
00485
00486 verbose() << "Field free Transport from " << zStart << " to "
00487 << z1 << endreq;
00488 TrackTransportStep tStep1 = TrackTransportStep( m_freeFieldExtrapolator, z1);
00489 transStepList.push_back(tStep1);
00490
00491
00492 verbose() << "Long Magnet region Transport from " << zStart
00493 << " to " << z2 << endreq;
00494 TrackTransportStep tStep2 = TrackTransportStep( m_longFieldExtrapolator, z2);
00495 transStepList.push_back(tStep2);
00496
00497
00498 verbose() << "Field free Transport from " << zStart << " to "
00499 << zTarget << endreq;
00500 TrackTransportStep tStep3 = TrackTransportStep(m_freeFieldExtrapolator, zTarget);
00501 transStepList.push_back(tStep3);
00502 }
00503
00504
00505 return StatusCode::SUCCESS;
00506 }
00507
00508
00509
00510 StatusCode TrackFirstCleverExtrapolator::thinScatter(State& state,
00511 double radLength){
00512
00513
00514
00515 double scatLength = 0.;
00516 double norm2 = 1.0+gsl_pow_2(state.tx())+gsl_pow_2(state.ty());
00517
00518 if (radLength >TrackParameters::lowTolerance){
00519 double radThick = sqrt(norm2)*radLength;
00520
00521 scatLength = radThick*gsl_pow_2(TrackParameters::moliereFactor*
00522 (1.+0.038*log(radThick)));
00523 }
00524
00525
00526 double p = GSL_MAX(state.p(),1.0*MeV);
00527
00528 double cnoise = m_fms2 * scatLength/gsl_pow_2(p);
00529
00530
00531 HepSymMatrix Q = HepSymMatrix(5,0);
00532
00533 Q.fast(3,3) = norm2 * (1. + gsl_pow_2(state.tx())) * cnoise;
00534 Q.fast(4,4) = norm2 * (1. + gsl_pow_2(state.ty())) * cnoise;
00535 Q.fast(4,3) = norm2 * state.tx() * state.ty() * cnoise;
00536
00537
00538 HepSymMatrix& tC = state.covariance();
00539 tC += Q;
00540
00541 return StatusCode::SUCCESS;
00542
00543 }
00544
00545
00546 StatusCode TrackFirstCleverExtrapolator::thickScatter( State& state,
00547 double tWall,
00548 double radLength )
00549 {
00550
00551 double scatLength = 0.;
00552 double norm2 = 1.0 + gsl_pow_2(state.tx()) + gsl_pow_2(state.ty());
00553 if (radLength > TrackParameters::lowTolerance){
00554 double radThick = sqrt(norm2)*radLength;
00555
00556 scatLength = radThick * gsl_pow_2(TrackParameters::moliereFactor *
00557 (1. + 0.038*log(radThick)));
00558 }
00559
00560
00561 double p = GSL_MAX( state.p(), 1.0 * MeV );
00562 double cnoise = m_fms2 * scatLength / gsl_pow_2(p);
00563
00564
00565 double covTxTx = norm2 * (1. + gsl_pow_2(state.tx())) * cnoise;
00566 double covTyTy = norm2 * (1. + gsl_pow_2(state.ty())) * cnoise;
00567 double covTxTy = norm2 * state.tx() * state.ty() * cnoise;
00568
00569
00570 double D = (m_upStream) ? -1. : 1. ;
00571
00572 HepSymMatrix Q(5,0);
00573
00574 Q.fast(1,1) = covTxTx * gsl_pow_2(tWall) / 3.;
00575 Q.fast(2,1) = covTxTy * gsl_pow_2(tWall) / 3.;
00576 Q.fast(3,1) = 0.5*covTxTx * D * tWall;
00577 Q.fast(4,1) = 0.5*covTxTy * D * tWall;
00578
00579 Q.fast(2,2) = covTyTy * gsl_pow_2(tWall) / 3.;
00580 Q.fast(3,2) = 0.5*covTxTy * D * tWall;
00581 Q.fast(4,2) = 0.5*covTyTy * D * tWall;
00582
00583 Q.fast(3,3) = covTxTx;
00584 Q.fast(4,3) = covTxTy;
00585
00586 Q.fast(4,4) = covTyTy;
00587
00588
00589 HepSymMatrix& tC = state.covariance();
00590 tC += Q;
00591
00592 return StatusCode::SUCCESS;
00593
00594 }
00595
00596 StatusCode TrackFirstCleverExtrapolator::energyLoss( State& state,
00597 double tWall,
00598 const Material* aMaterial)
00599 {
00600
00601 double norm = sqrt(1.0+gsl_pow_2(state.tx())+gsl_pow_2(state.ty()));
00602 double bbLoss = tWall * norm * aMaterial->density() * m_energyLoss *
00603 aMaterial->Z() / aMaterial->A();
00604 bbLoss = GSL_MIN(m_eMax, bbLoss);
00605 if (m_upStream == false){
00606 bbLoss *= -1.0;
00607 }
00608
00609
00610 HepVector& tX = state.state();
00611
00612 if (tX[4]>0.){
00613 tX[4] = 1./(1./tX[4]+(bbLoss));
00614 }
00615 else{
00616 tX[4] = 1./(1./tX[4]-(bbLoss));
00617 }
00618
00619 return StatusCode::SUCCESS;
00620
00621 }
00622
00623 StatusCode TrackFirstCleverExtrapolator::electronEnergyLoss(State& state,
00624 double radLength)
00625 {
00626
00627
00628 double t;
00629 double norm = sqrt(1.0+gsl_pow_2(state.tx())+gsl_pow_2(state.ty()));
00630
00631 if (m_upStream){
00632 t = radLength*norm;
00633 }
00634 else{
00635 t = -radLength*norm;
00636 }
00637
00638
00639 if (fabs(t)>m_tMax) t = GSL_SIGN(t)*m_tMax;
00640
00641
00642 HepVector& tX = state.state();
00643 HepSymMatrix& tC = state.covariance();
00644
00645 tC.fast(5,5) += gsl_pow_2(tX[4]) * (exp(-t*log(3.0)/log(2.0))-exp(-2.0*t));
00646 tX(4) *= exp(-t);
00647
00648 return StatusCode::SUCCESS;
00649 }
00650
00651 double TrackFirstCleverExtrapolator::zScatter( const double z1,
00652 const double z2 ) const
00653 {
00654 double zS;
00655 if (fabs(z1-z2) <= m_thickWall){
00656
00657 zS = 0.5*(z1+z2);
00658 }
00659 else {
00660
00661 if (m_upStream == true){
00662 zS = GSL_MIN(z1,z2);
00663 }
00664 else {
00665 zS = GSL_MAX(z1,z2);
00666 }
00667 }
00668 return zS;
00669 }