CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/src/TrackPropagation/NavPropagator/src/NavPropagator.cc

Go to the documentation of this file.
00001 #include "TrackPropagation/NavPropagator/interface/NavPropagator.h"
00002 #include "MagneticField/VolumeBasedEngine/interface/VolumeBasedMagneticField.h"
00003 #include "TrackingTools/GeomPropagators/interface/PropagationExceptions.h"
00004 #include  "TrackPropagation/NavGeometry/interface/NavVolume6Faces.h"
00005 // magVolume6Faces needed to get access to volume name and material:
00006 #include "MagneticField/VolumeGeometry/interface/MagVolume6Faces.h"
00007 //
00008 #include "TrackPropagation/RungeKutta/interface/RKPropagatorInS.h"
00009 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00010 #include "DataFormats/GeometrySurface/interface/PlaneBuilder.h"
00011 
00012 #include "TrackingTools/MaterialEffects/interface/VolumeMaterialEffectsEstimate.h"
00013 
00014 using namespace std;
00015 
00016 NavPropagator::NavPropagator( const MagneticField* field,
00017                               PropagationDirection dir) :
00018   Propagator(dir),
00019   theAirMedium(3.e4, 1.3e-3*0.000307075*0.5/2),
00020   theIronMedium(1.76,7.87*0.000307075*0.46556/2),
00021   theMSEstimator(0.105), theELEstimator(0.105)
00022 {
00023   theField = dynamic_cast<const VolumeBasedMagneticField*>(field);
00024   //FIXME: iron volumes are hard-coded below... will change with new .xml geometry MM 28/6/07
00025   int myIronVolumes[126] = {6,9,11,14,15,18,22,23,26,29,30,33,36,37,43,46,49,53,56,57,60,62,
00026                             63,65,71,77,105,106,107,111,112,113,114,115,116,117,118,122,123,
00027                             125,126,128,129,130,131,132,133,135,137,141,145,147,148,149,153,
00028                             154,155,156,157,158,159,160,164,165,167,168,170,171,172,173,174,
00029                             175,177,178,179,180,184,185,186,187,188,189,190,191,195,196,198,
00030                             200,204,208,210,211,212,216,217,218,219,220,221,222,223,227,228,
00031                             230,231,233,234,235,236,237,238,240,241,242,243,247,248,249,250,
00032                             251,252,253,254,258,259,261}; 
00033   for(int i=0; i<272; i++) isIronVolume[i]=false;
00034   for(int i=0; i<126 ; i++) isIronVolume[myIronVolumes[i]]=true; 
00035   //  for(int i=1; i<272 ; i++) {
00036   //  if(isIronVolume[i]) std::cout << "Volume no." << i << " is made of iron " << std::endl;
00037   //  if(!isIronVolume[i]) std::cout << "Volume no." << i << " is made of air " << std::endl;
00038   //}
00039 }
00040 
00041 NavPropagator::~NavPropagator() {
00042     for (MagVolumeMap::iterator i = theNavVolumeMap.begin(); i != theNavVolumeMap.end(); ++i) {
00043       delete i->second;
00044     }
00045 }
00046 
00047 const MagneticField*  NavPropagator::magneticField() const {return theField;}
00048 
00049 std::pair<TrajectoryStateOnSurface,double> 
00050 NavPropagator::propagateWithPath(const TrajectoryStateOnSurface& inputState, 
00051                                  const Plane& targetPlane) const
00052 {
00053 
00054    LogDebug("NavPropagator") <<  "NavPropagator::propagateWithPath(TrajectoryStateOnSurface, Plane) called with "
00055        << inputState;
00056 
00057   VolumeCrossReturnType exitState( 0, inputState, 0.0);
00058   TSOS startingState = inputState;
00059   TSOS TempState = inputState;
00060   const NavVolume* currentVolume = 0; // explicit initialization to get rid of compiler warning
00061 
00062   int count = 0;
00063   int maxCount = 100;
00064   while (!destinationCrossed( startingState, TempState, targetPlane)) {
00065 
00066      LogDebug("NavPropagator") <<  "NavPropagator:: at beginning of while loop at iteration " << count ;
00067 
00068     startingState = TempState;
00069     bool isReflected = false;
00070 
00071     if (exitState.volume() != 0) { // next volume connected
00072       currentVolume = exitState.volume();
00073     }
00074     else {
00075       // 1 mm shifted peek is necessary only because geometry is not yet glued and exists only for z<0
00076       GlobalPoint gp = startingState.globalPosition() + 0.1*startingState.globalMomentum().unit();
00077 
00078       if (gp.z()>0) { // Reflect in Z (as long as MagVolumes exist only for z<0
00079         GlobalTrajectoryParameters gtp( GlobalPoint(startingState.globalPosition().x(),
00080                                                        startingState.globalPosition().y(),
00081                                                     -startingState.globalPosition().z()),
00082                                         GlobalVector(startingState.globalMomentum().x(),
00083                                                        startingState.globalMomentum().y(),
00084                                                        -startingState.globalMomentum().z()),
00085                                         startingState.globalParameters().charge(), theField );
00086         FreeTrajectoryState fts(gtp);
00087         TempState = TSOS( fts, startingState.surface());
00088         isReflected = true;
00089       }
00090       currentVolume = findVolume( TempState );
00091       if (currentVolume == 0) {
00092          std::cout <<  "NavPropagator: findVolume failed to find volume containing point "
00093              << startingState.globalPosition() ;
00094         return std::pair<TrajectoryStateOnSurface,double>(noNextVolume( startingState), 0);
00095       }
00096     }
00097 
00098     PropagatorType currentPropagator( *currentVolume);
00099 
00100     LogDebug("NavPropagator") <<  "NavPropagator: calling crossToNextVolume" ;
00101     VolumeCrossReturnType exitStateNM = currentVolume->crossToNextVolume( TempState, currentPropagator);
00102     LogDebug("NavPropagator") <<  "NavPropagator: crossToNextVolume returned" ;
00103     LogDebug("NavPropagator") <<  "Volume pointer: " << exitState.volume() << " and new ";
00104     LogDebug("NavPropagator") <<  exitState.tsos() ;
00105     LogDebug("NavPropagator") <<  "So that was a path length " << exitState.path() ;
00106     
00107     
00108     if (exitStateNM.tsos().isValid()) { 
00109       // try to add material effects !!
00110       //FIXME: smarter way of treating material effects is needed! Now only Iron/Air... 
00111       VolumeMediumProperties thisMedium = currentVolume->isIron()? theIronMedium:theAirMedium;
00112       VolumeMaterialEffectsEstimate msEstimate(theMSEstimator.estimate(exitStateNM.tsos(),
00113                                                                        exitStateNM.path(),
00114                                                                        thisMedium));
00115       VolumeMaterialEffectsEstimate elEstimate(theELEstimator.estimate(exitStateNM.tsos(),
00116                                                                        exitStateNM.path(),
00117                                                                        thisMedium));
00118       std::vector<const VolumeMaterialEffectsEstimate*> matEstimates;
00119       matEstimates.push_back(&msEstimate);
00120       matEstimates.push_back(&elEstimate);
00121       exitState = VolumeCrossReturnType(exitStateNM.volume(),
00122                                         theMaterialUpdator.updateState(exitStateNM.tsos(),alongMomentum,matEstimates),
00123                                         exitStateNM.path());
00124     } else { 
00125       exitState = exitStateNM; 
00126     }
00127     
00128     
00129     if ( !exitState.tsos().isValid()) {
00130       // return propagateInVolume( currentVolume, startingState, targetPlane);
00131        std::cout <<  "NavPropagator: failed to crossToNextVolume in volume at pos "
00132            << currentVolume->position();
00133       break;
00134     }
00135     else {
00136        LogDebug("NavPropagator") <<  "NavPropagator: crossToNextVolume reached volume ";
00137       if (exitState.volume() != 0) {       
00138          LogDebug("NavPropagator") <<  " at pos "
00139              << exitState.volume()->position() 
00140              << "with state " << exitState.tsos() ;
00141       }
00142       else  LogDebug("NavPropagator") <<  " unknown";
00143     }
00144 
00145     TempState = exitState.tsos();
00146 
00147     if (fabs(exitState.path())<0.01) {
00148       LogDebug("NavPropagator") <<  "failed to move at all!! at position: " << exitState.tsos().globalPosition();
00149 
00150       GlobalTrajectoryParameters gtp( exitState.tsos().globalPosition()+0.01*exitState.tsos().globalMomentum().unit(),
00151                                       exitState.tsos().globalMomentum(),
00152                                       exitState.tsos().globalParameters().charge(), theField );
00153 
00154       FreeTrajectoryState fts(gtp);
00155       TSOS ShiftedState( fts, exitState.tsos().surface());
00156       //      exitState.tsos() = ShiftedState;
00157       TempState = ShiftedState;
00158 
00159       LogDebug("NavPropagator") <<  "Shifted to new position " << TempState.globalPosition();
00160 
00161     }
00162 
00163 
00164     //      std::cout << "Just moved " << exitState.path() << " cm through " << ( currentVolume->isIron()? "IRON":"AIR" ); 
00165     // std::cout << " at radius: " << TempState.globalPosition().perp();
00166     //  std::cout << " and lost " << exitStateNM.tsos().globalMomentum().mag()-exitState.tsos().globalMomentum().mag() << " GeV of Energy !!!! New energy: " << exitState.tsos().globalMomentum().mag() << std::endl;
00167     // reflect back to normal universe if necessary:
00168     if (isReflected) { // reflect back... nobody should know we secretely z-reflected the tsos 
00169       
00170 
00171       GlobalTrajectoryParameters gtp( GlobalPoint(TempState.globalPosition().x(),
00172                                                      TempState.globalPosition().y(),
00173                                                   -TempState.globalPosition().z()),
00174                                       GlobalVector(TempState.globalMomentum().x(),
00175                                                    TempState.globalMomentum().y(),
00176                                                    -TempState.globalMomentum().z()),
00177                                       TempState.globalParameters().charge(), theField );
00178 
00179       FreeTrajectoryState fts(gtp);
00180       TSOS ReflectedState( fts, TempState.surface());
00181       TempState = ReflectedState;
00182       isReflected = false;
00183     }
00184 
00185     ++count;
00186     if (count > maxCount) {
00187        LogDebug("NavPropagator") <<  "Ohoh, NavPropagator in infinite loop, count = " << count;
00188       return TsosWP();
00189     }
00190 
00191   }
00192 
00193   
00194 
00195   // Arriving here only if destinationCrossed or if crossToNextVolume returned invalid state,
00196   // in which case we should check if the targetPlane is not crossed in the current volume
00197 
00198   return propagateInVolume( currentVolume, startingState, targetPlane);  
00199 
00200 }
00201 
00202 
00203 const NavVolume* NavPropagator::findVolume( const TrajectoryStateOnSurface& inputState) const
00204 {
00205    LogDebug("NavPropagator") <<  "NavPropagator: calling theField->findVolume ";
00206 
00207   GlobalPoint gp = inputState.globalPosition() + 0.1*inputState.globalMomentum().unit();
00208   // Next protection only needed when 1 mm linear move crosses the z==0 plane:
00209   GlobalPoint gpSym(gp.x(), gp.y(), (gp.z()<0? gp.z() : -gp.z()));
00210 
00211   const MagVolume* magVolume = theField->findVolume( gpSym);
00212 
00213    LogDebug("NavPropagator") <<  "NavPropagator: got MagVolume* " << magVolume 
00214        << " when searching with pos " << gpSym ;
00215 
00216 
00217    if (!magVolume) {
00218      cout << "Got invalid volume pointer " << magVolume << " at position " << gpSym;
00219      return 0;
00220    } 
00221   return navVolume(magVolume);
00222 }
00223 
00224 
00225 const NavVolume* NavPropagator::navVolume( const MagVolume* magVolume)  const
00226 {
00227   NavVolume* result;
00228   MagVolumeMap::iterator i = theNavVolumeMap.find( magVolume);
00229   if (i == theNavVolumeMap.end()) {
00230     // Create a NavVolume from a MagVolume if the NavVolume doesn't exist yet
00231     // FIXME: hardcoded iron/air classification should be made into something more general
00232     // will break with new magnetic field volume .xml file MM 28/6/07
00233     const MagVolume6Faces* pVol6 = dynamic_cast<const MagVolume6Faces*> ( magVolume );
00234     int n=0;
00235     bool isIron=false;
00236     if(pVol6) { 
00237       std::stringstream ss(pVol6->name.substr(5));
00238       ss >> n;
00239       //      std::cout << " Found volume with number " << n << std::endl;
00240     } else {
00241       std::cout << "Error (NavVolume6Faces) failed to get MagVolume6Faces pointer" << std::endl;
00242     }
00243     if(n<1 || n>271) {
00244       std::cout << "Error (NavVolume6Faces) unexpected Volume number!" << std::endl;
00245     } else {
00246       isIron = isIronVolume[n];
00247     }
00248 
00249     result= new NavVolume6Faces( *magVolume, isIron);
00250     theNavVolumeMap[magVolume] = result;
00251   }
00252   else result = i->second;
00253   return result;
00254 }
00255 
00256 std::pair<TrajectoryStateOnSurface,double> 
00257 NavPropagator::propagateInVolume( const NavVolume* currentVolume, 
00258                                   const TrajectoryStateOnSurface& startingState, 
00259                                   const Plane& targetPlane) const
00260 {
00261   PropagatorType prop( *currentVolume);
00262 
00263   // OK, fix is rather ugly for now: need to reflect z>0 states to z<0 MM 25/6/07
00264   bool isReflected = false;
00265   TSOS okState = startingState;
00266   PlaneBuilder::ReturnType ReflectedPlane;
00267   Plane okPlane = targetPlane;
00268   
00269   if (startingState.globalPosition().z()>0 || 
00270       (fabs(startingState.globalPosition().z())<1.e-4 && startingState.globalMomentum().z()>1.e-4)) {
00271     GlobalTrajectoryParameters gtp( GlobalPoint(startingState.globalPosition().x(),
00272                                                 startingState.globalPosition().y(),
00273                                                 -startingState.globalPosition().z()),
00274                                     GlobalVector(startingState.globalMomentum().x(),
00275                                                  startingState.globalMomentum().y(),
00276                                                  -startingState.globalMomentum().z()),
00277                                     startingState.globalParameters().charge(), prop.magneticField() );
00278     
00279     FreeTrajectoryState fts(gtp);
00280     TSOS ReflectedState( fts, startingState.surface());
00281     okState = ReflectedState;
00282       
00283     GlobalVector TempVec = targetPlane.normalVector();
00284     GlobalVector ReflectedVector = GlobalVector ( TempVec.x(), TempVec.y(), -TempVec.z());
00285     GlobalVector zAxis = ReflectedVector.unit();
00286     GlobalVector yAxis( zAxis.y(), -zAxis.x(), 0);
00287     GlobalVector xAxis = yAxis.cross( zAxis);
00288     Surface::RotationType rot = Surface::RotationType( xAxis, yAxis, zAxis);
00289 
00290     GlobalPoint gp = targetPlane.position();
00291     GlobalPoint gpSym(gp.x(), gp.y(), -gp.z());
00292     PlaneBuilder pb;
00293     ReflectedPlane = pb.plane( gpSym, rot);
00294     
00295     okPlane =  *ReflectedPlane;
00296     isReflected = true;    
00297   }
00298   
00299   // Done Reflecting
00300 
00301 
00302   TsosWP res = prop.propagateWithPath( okState, okPlane);
00303 
00304   // Now reflect back the result if necessary...
00305   if (isReflected && res.first.isValid()) { // reflect back... nobody should know we secretely z-reflected the tsos 
00306    
00307 
00308     TSOS TempState = res.first; 
00309     GlobalTrajectoryParameters gtp( GlobalPoint(TempState.globalPosition().x(),
00310                                                 TempState.globalPosition().y(),
00311                                                 -TempState.globalPosition().z()),
00312                                     GlobalVector(TempState.globalMomentum().x(),
00313                                                  TempState.globalMomentum().y(),
00314                                                  -TempState.globalMomentum().z()),
00315                                     TempState.globalParameters().charge(), prop.magneticField() );
00316     
00317     FreeTrajectoryState fts(gtp);
00318     TSOS ReflectedState( fts, TempState.surface());
00319     res.first = ReflectedState;
00320     isReflected = false;
00321   }
00322   // Done Reflecting back !
00323 
00324   if (res.first.isValid()) {
00325 
00326     GlobalPoint gp = res.first.globalPosition();
00327     GlobalPoint gpSym(gp.x(), gp.y(), (gp.z()<0? gp.z() : -gp.z()));
00328  
00329     if (currentVolume->inside( gpSym )) {
00330 
00331       //FIXME: smarter way of treating material effects is needed! Now only Iron/Air... 
00332       VolumeMediumProperties thisMedium = currentVolume->isIron()? theIronMedium:theAirMedium;
00333 
00334       //
00335       // try to add material effects
00336       //
00337       VolumeMaterialEffectsEstimate msEstimate(theMSEstimator.estimate(res.first,
00338                                                                        res.second,
00339                                                                        thisMedium));
00340       VolumeMaterialEffectsEstimate elEstimate(theELEstimator.estimate(res.first,
00341                                                                        res.second,
00342                                                                        thisMedium));
00343       std::vector<const VolumeMaterialEffectsEstimate*> matEstimates;
00344       matEstimates.push_back(&msEstimate);
00345       matEstimates.push_back(&elEstimate);
00346       TSOS newState = theMaterialUpdator.updateState(res.first,alongMomentum,matEstimates);
00347       return TsosWP(newState,res.second);
00348     }
00349     // sometimes fails when propagation on plane and surface are less than 0.1 mm apart... 
00350   } 
00351 
00352   //  return TsosWP( TrajectoryStateOnSurface(), 0); // Gives 'double free' errors... return res even when Outside volume... 
00353   return res;
00354 
00355 }
00356 
00357 bool  NavPropagator::destinationCrossed( const TSOS& startState,
00358                                          const TSOS& endState, const Plane& plane) const
00359 {
00360   bool res = ( plane.side( startState.globalPosition(), 1.e-6) != 
00361                plane.side( endState.globalPosition(), 1.e-6));
00362   /*
00363    LogDebug("NavPropagator") <<  "NavPropagator::destinationCrossed called with startState "
00364        << startState << std::endl
00365        << " endState " << endState 
00366        << std::endl
00367        << " plane at " << plane.position()
00368        << std::endl;
00369 
00370    LogDebug("NavPropagator") <<  "plane.side( startState) " << plane.side( startState.globalPosition(), 1.e-6);
00371    LogDebug("NavPropagator") <<  "plane.side( endState)   " << plane.side( endState.globalPosition(), 1.e-6);
00372   */
00373 
00374   return res;
00375 }
00376 
00377 TrajectoryStateOnSurface 
00378 NavPropagator::noNextVolume( TrajectoryStateOnSurface startingState) const
00379 {
00380    LogDebug("NavPropagator") <<  std::endl
00381        << "Propagation reached end of volume geometry without crossing target surface" 
00382        << std::endl
00383        << "starting state of last propagation " << startingState;
00384 
00385   return TrajectoryStateOnSurface();
00386 }
00387 
00388 
00389 
00390 std::pair<TrajectoryStateOnSurface,double> 
00391 NavPropagator::propagateWithPath(const FreeTrajectoryState& fts, 
00392                                  const Cylinder& cylinder) const
00393 {
00394    LogDebug("NavPropagator") <<  "propagateWithPath(const FreeTrajectoryState&) not implemented yet in NavPropagator" ;
00395   return TsosWP();
00396 }
00397 std::pair<TrajectoryStateOnSurface,double> 
00398 NavPropagator::propagateWithPath(const FreeTrajectoryState& fts, 
00399                                  const Plane& cylinder) const
00400 {
00401    LogDebug("NavPropagator") <<  "propagateWithPath(const FreeTrajectoryState&) not implemented yet in NavPropagator" ;
00402   return TsosWP();
00403 }