CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/TrackPropagation/Geant4e/src/Geant4ePropagator.cc

Go to the documentation of this file.
00001 
00002 //Geant4e
00003 #include "TrackPropagation/Geant4e/interface/Geant4ePropagator.h"
00004 #include "TrackPropagation/Geant4e/interface/ConvertFromToCLHEP.h"
00005 #include "TrackPropagation/Geant4e/interface/Geant4eSteppingAction.h"
00006 
00007 //CMSSW
00008 #include "MagneticField/Engine/interface/MagneticField.h"
00009 #include "DataFormats/TrajectorySeed/interface/PropagationDirection.h"
00010 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00011 #include "TrackingTools/TrajectoryState/interface/SurfaceSideDefinition.h"
00012 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00013 #include "DataFormats/GeometrySurface/interface/Plane.h"
00014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00015 
00016 //Geant4
00017 #include "G4ErrorFreeTrajState.hh"
00018 #include "G4ErrorPlaneSurfaceTarget.hh"
00019 #include "G4ErrorCylSurfaceTarget.hh"
00020 #include "G4ErrorPropagatorData.hh"
00021 #include "G4EventManager.hh"
00022 #include "G4SteppingControl.hh"
00023 
00024 //CLHEP
00025 #include "CLHEP/Units/GlobalSystemOfUnits.h"
00026 
00027 
00030 Geant4ePropagator::Geant4ePropagator(const MagneticField* field,
00031                                      const char* particleName,
00032                                      PropagationDirection dir):
00033   Propagator(dir),
00034   theField(field),
00035   theParticleName(particleName),
00036   theG4eManager(G4ErrorPropagatorManager::GetErrorPropagatorManager()),
00037   theSteppingAction(0) {
00038 
00039   G4ErrorPropagatorData::SetVerbose(0);
00040 }
00041 
00044 Geant4ePropagator::~Geant4ePropagator() {
00045 }
00046 
00047 //
00049 //
00050 
00055 TrajectoryStateOnSurface 
00056 Geant4ePropagator::propagate (const FreeTrajectoryState& ftsStart, 
00057                               const Plane& pDest) const {
00058 
00059   if(theG4eManager->PrintG4ErrorState() == "G4ErrorState_PreInit")
00060     theG4eManager->InitGeant4e();
00061 
00062   if (!theSteppingAction) {
00063     theSteppingAction = new Geant4eSteppingAction;
00064     theG4eManager->SetUserAction(theSteppingAction);
00065   }
00066 
00068   // Construct the target surface
00069   //
00070 
00071   //* Get position and normal (orientation) of the destination plane
00072   GlobalPoint posPlane = pDest.toGlobal(LocalPoint(0,0,0));
00073   GlobalVector normalPlane = pDest.toGlobal(LocalVector(0,0,1.)); 
00074   normalPlane = normalPlane.unit();
00075 
00076   //* Transform this into HepGeom::Point3D<double>  and HepGeom::Normal3D<double>  that define a plane for
00077   //  Geant4e.
00078   //  CMS uses cm and GeV while Geant4 uses mm and MeV
00079   HepGeom::Point3D<double>   surfPos  = 
00080     TrackPropagation::globalPointToHepPoint3D(posPlane);
00081   HepGeom::Normal3D<double>  surfNorm = 
00082     TrackPropagation::globalVectorToHepNormal3D(normalPlane);
00083 
00084   //DEBUG
00085   LogDebug("Geant4e") << "G4e -  Destination CMS plane position:" << posPlane << "cm\n"
00086                       << "G4e -                  (Ro, eta, phi): (" 
00087                       << posPlane.perp() << " cm, " 
00088                       << posPlane.eta() << ", " 
00089                       << posPlane.phi().degrees() << " deg)\n"
00090                       << "G4e -  Destination G4  plane position: " << surfPos
00091                       << " mm, Ro = " << surfPos.perp() << " mm";
00092   LogDebug("Geant4e") << "G4e -  Destination CMS plane normal  : " 
00093                       << normalPlane << "\n"
00094                       << "G4e -  Destination G4  plane normal  : " 
00095                       << normalPlane;
00096   LogDebug("Geant4e") << "G4e -  Distance from plane position to plane: " 
00097                       << pDest.localZ(posPlane) << " cm";
00098   //DEBUG
00099 
00100   //* Set the target surface
00101   G4ErrorSurfaceTarget* g4eTarget = new G4ErrorPlaneSurfaceTarget(surfNorm,
00102                                                                   surfPos);
00103 
00104   //g4eTarget->Dump("G4e - ");
00105   //
00107 
00109   // Find initial point
00110   //
00111 
00112   // * Get the starting point and direction and convert them to CLHEP::Hep3Vector 
00113   //   for G4. CMS uses cm and GeV while Geant4 uses mm and MeV
00114   GlobalPoint  cmsInitPos = ftsStart.position();
00115   GlobalVector cmsInitMom = ftsStart.momentum();
00116 
00117   CLHEP::Hep3Vector g4InitPos = 
00118     TrackPropagation::globalPointToHep3Vector(cmsInitPos);
00119   CLHEP::Hep3Vector g4InitMom = 
00120     TrackPropagation::globalVectorToHep3Vector(cmsInitMom*GeV);
00121 
00122   //DEBUG
00123   LogDebug("Geant4e") << "G4e -  Initial CMS point position:" << cmsInitPos 
00124                       << "cm\n"
00125                       << "G4e -              (Ro, eta, phi): (" 
00126                       << cmsInitPos.perp() << " cm, " 
00127                       << cmsInitPos.eta() << ", " 
00128                       << cmsInitPos.phi().degrees() << " deg)\n"
00129                       << "G4e -  Initial G4  point position: " << g4InitPos 
00130                       << " mm, Ro = " << g4InitPos.perp() << " mm";
00131   LogDebug("Geant4e") << "G4e -  Initial CMS momentum      :" << cmsInitMom 
00132                       << "GeV\n"
00133                       << "G4e -  Initial G4  momentum      : " << g4InitMom 
00134                       << " MeV";
00135   LogDebug("Geant4e") << "G4e -  Distance from initial point to plane: " 
00136                       << pDest.localZ(cmsInitPos) << " cm";
00137   //DEBUG
00138 
00139   //
00141 
00143   // Set particle name
00144   //
00145   int charge = ftsStart.charge();
00146   std::string particleName  = theParticleName;
00147 
00148   if (charge > 0) {
00149       particleName += "+";
00150   } else {
00151       particleName += "-";
00152   }
00153 
00154   LogDebug("Geant4e") << "G4e -  Particle name: " << particleName;
00155 
00156   //
00158 
00160   //Set the error and trajectories, and finally propagate
00161   //
00162   G4ErrorTrajErr g4error( 5, 1 );
00163   if(ftsStart.hasError()) {
00164     const CurvilinearTrajectoryError initErr = ftsStart.curvilinearError();
00165     g4error = TrackPropagation::algebraicSymMatrix55ToG4ErrorTrajErr( initErr , charge); //The error matrix
00166   }
00167   LogDebug("Geant4e") << "G4e -  Error matrix: " << g4error;
00168 
00169   G4ErrorFreeTrajState* g4eTrajState = 
00170     new G4ErrorFreeTrajState(particleName, g4InitPos, g4InitMom, g4error);
00171   LogDebug("Geant4e") << "G4e -  Traj. State: " << (*g4eTrajState);
00172 
00173   //Set the mode of propagation according to the propagation direction
00174   G4ErrorMode mode = G4ErrorMode_PropForwards;
00175 
00176   if (propagationDirection() == oppositeToMomentum) {
00177     mode = G4ErrorMode_PropBackwards;
00178     LogDebug("Geant4e") << "G4e -  Propagator mode is \'backwards\'";
00179   } else if(propagationDirection() == alongMomentum) {
00180     LogDebug("Geant4e") << "G4e -  Propagator mode is \'forwards\'";
00181   } else {   //Mode must be anyDirection then - need to figure out for Geant which it is
00182     std::cout << "Determining actual direction";
00183     if(pDest.localZ(cmsInitPos)*pDest.localZ(cmsInitMom) < 0) {
00184       LogDebug("Geant4e") << "G4e -  Propagator mode is \'forwards\'";
00185       std::cout << ", got forwards" << std::endl;
00186     } else {
00187       mode = G4ErrorMode_PropBackwards;
00188       LogDebug("Geant4e") << "G4e -  Propagator mode is \'backwards\'";
00189       std::cout << ", got backwards" << std::endl;
00190     }
00191   }
00192 
00193   //
00195 
00197   // Propagate
00198 
00199   int ierr;
00200   if(mode == G4ErrorMode_PropBackwards) {
00201     //To make geant transport the particle correctly need to give it the opposite momentum
00202     //because geant flips the B field bending and adds energy instead of subtracting it
00203     //but still wants the momentum "backwards"
00204     g4eTrajState->SetMomentum( -g4eTrajState->GetMomentum());
00205     ierr = theG4eManager->Propagate( g4eTrajState, g4eTarget, mode);
00206     g4eTrajState->SetMomentum( -g4eTrajState->GetMomentum());
00207   } else {
00208     ierr = theG4eManager->Propagate( g4eTrajState, g4eTarget, mode);
00209   }
00210   LogDebug("Geant4e") << "G4e -  Return error from propagation: " << ierr;
00211 
00212   if(ierr!=0) {
00213     LogDebug("Geant4e") << "G4e - Error is not 0, returning invalid trajectory";
00214     return TrajectoryStateOnSurface();
00215   }
00216 
00217   //
00219 
00221   // Retrieve the state in the end from Geant4e, convert them to CMS vectors
00222   // and points, and build global trajectory parameters.
00223   // CMS uses cm and GeV while Geant4 uses mm and MeV
00224   //
00225   HepGeom::Point3D<double>  posEnd = g4eTrajState->GetPosition();
00226   HepGeom::Vector3D<double>  momEnd = g4eTrajState->GetMomentum();
00227 
00228   GlobalPoint  posEndGV = TrackPropagation::hepPoint3DToGlobalPoint(posEnd);
00229   GlobalVector momEndGV = TrackPropagation::hep3VectorToGlobalVector(momEnd)/GeV;
00230 
00231   //DEBUG
00232   LogDebug("Geant4e") << "G4e -  Final CMS point position:" << posEndGV 
00233                       << "cm\n"
00234                       << "G4e -            (Ro, eta, phi): (" 
00235                       << posEndGV.perp() << " cm, " 
00236                       << posEndGV.eta() << ", " 
00237                       << posEndGV.phi().degrees() << " deg)\n"
00238                       << "G4e -  Final G4  point position: " << posEnd 
00239                       << " mm,\tRo =" << posEnd.perp()  << " mm";
00240   LogDebug("Geant4e") << "G4e -  Final CMS momentum      :" << momEndGV
00241                       << "GeV\n"
00242                       << "G4e -  Final G4  momentum      : " << momEnd 
00243                       << " MeV";
00244   LogDebug("Geant4e") << "G4e -  Distance from final point to plane: " 
00245                       << pDest.localZ(posEndGV) << " cm";
00246   //DEBUG
00247 
00248   GlobalTrajectoryParameters tParsDest(posEndGV, momEndGV, charge, theField);
00249 
00250 
00251   // Get the error covariance matrix from Geant4e. It comes in curvilinear
00252   // coordinates so use the appropiate CMS class  
00253   G4ErrorTrajErr g4errorEnd = g4eTrajState->GetError();
00254   CurvilinearTrajectoryError 
00255     curvError(TrackPropagation::g4ErrorTrajErrToAlgebraicSymMatrix55(g4errorEnd, charge));
00256   LogDebug("Geant4e") << "G4e -  Error matrix after propagation: " << g4errorEnd;
00257 
00259   // We set the SurfaceSide to atCenterOfSurface.                       //
00261   LogDebug("Geant4e") << "G4e -  SurfaceSide is always atCenterOfSurface after propagation";
00262   SurfaceSideDefinition::SurfaceSide side = SurfaceSideDefinition::atCenterOfSurface;
00263   //
00265 
00266   return TrajectoryStateOnSurface(tParsDest, curvError, pDest, side);
00267 }
00268 
00269 //Require method with input TrajectoryStateOnSurface to be used in track fitting
00270 //Don't need extra info about starting surface; use regular propagation method
00271 TrajectoryStateOnSurface
00272 Geant4ePropagator::propagate (const TrajectoryStateOnSurface& tsos, const Plane& plane) const {
00273   const FreeTrajectoryState ftsStart = *tsos.freeState();
00274   return propagate(ftsStart,plane);
00275 }
00276 
00277 
00281 TrajectoryStateOnSurface 
00282 Geant4ePropagator::propagate (const FreeTrajectoryState& ftsStart, 
00283                               const Cylinder& cDest) const {
00284 
00285   if(theG4eManager->PrintG4ErrorState() == "G4ErrorState_PreInit")
00286     theG4eManager->InitGeant4e();
00287   if (!theSteppingAction) {
00288     theSteppingAction = new Geant4eSteppingAction;
00289     theG4eManager->SetUserAction(theSteppingAction);
00290   }
00291 
00292   //Get Cylinder parameters.
00293   //CMS uses cm and GeV while Geant4 uses mm and MeV.
00294   // - Radius
00295   G4float radCyl = cDest.radius()*cm;
00296   // - Position: PositionType & GlobalPoint are Basic3DPoint<float,GlobalTag>
00297   G4ThreeVector posCyl = 
00298     TrackPropagation::globalPointToHep3Vector(cDest.position());
00299   // - Rotation: Type in CMSSW is RotationType == TkRotation<T>, T=float
00300   G4RotationMatrix rotCyl = 
00301     TrackPropagation::tkRotationFToHepRotation(cDest.rotation());
00302 
00303   //DEBUG
00304   TkRotation<float>  rotation = cDest.rotation();
00305   LogDebug("Geant4e") << "G4e -  TkRotation" << rotation;
00306   LogDebug("Geant4e") << "G4e -  G4Rotation" << rotCyl << "mm";
00307 
00308 
00309   //Set the target surface
00310   G4ErrorSurfaceTarget* g4eTarget = new G4ErrorCylSurfaceTarget(radCyl, posCyl,
00311                                                                 rotCyl);
00312 
00313   //DEBUG
00314   LogDebug("Geant4e") << "G4e -  Destination CMS cylinder position:" << cDest.position() << "cm\n"
00315                       << "G4e -  Destination CMS cylinder radius:" << cDest.radius() << "cm\n"
00316                       << "G4e -  Destination CMS cylinder rotation:" << cDest.rotation() << "\n";
00317   LogDebug("Geant4e") << "G4e -  Destination G4  cylinder position: " << posCyl << "mm\n"
00318                       << "G4e -  Destination G4  cylinder radius:" << radCyl << "mm\n"
00319                       << "G4e -  Destination G4  cylinder rotation:" << rotCyl << "\n";
00320 
00321 
00322   //Get the starting point and direction and convert them to CLHEP::Hep3Vector for G4
00323   //CMS uses cm and GeV while Geant4 uses mm and MeV
00324   GlobalPoint  cmsInitPos = ftsStart.position();
00325   GlobalVector cmsInitMom = ftsStart.momentum();
00326 
00327   CLHEP::Hep3Vector g4InitMom = 
00328     TrackPropagation::globalVectorToHep3Vector(cmsInitMom*GeV);
00329   CLHEP::Hep3Vector g4InitPos = 
00330     TrackPropagation::globalPointToHep3Vector(cmsInitPos);
00331 
00332   //DEBUG
00333   LogDebug("Geant4e") << "G4e -  Initial CMS point position:" << cmsInitPos 
00334                       << "cm\n"
00335                       << "G4e -              (Ro, eta, phi): (" 
00336                       << cmsInitPos.perp() << " cm, " 
00337                       << cmsInitPos.eta() << ", " 
00338                       << cmsInitPos.phi().degrees() << " deg)\n"
00339                       << "G4e -  Initial G4  point position: " << g4InitPos 
00340                       << " mm, Ro = " << g4InitPos.perp() << " mm";
00341   LogDebug("Geant4e") << "G4e -  Initial CMS momentum      :" << cmsInitMom 
00342                       << "GeV\n"
00343                       << "G4e -  Initial G4  momentum      : " << g4InitMom 
00344                       << " MeV";
00345 
00346   //Set particle name
00347   int charge = ftsStart.charge();
00348   std::string particleName  = theParticleName;
00349   if (charge > 0)
00350     particleName += "+";
00351   else
00352     particleName += "-";
00353   LogDebug("Geant4e") << "G4e -  Particle name: " << particleName;
00354 
00355   //Set the error and trajectories, and finally propagate
00356   G4ErrorTrajErr g4error( 5, 1 );
00357   if(ftsStart.hasError()) {
00358     const CurvilinearTrajectoryError initErr = ftsStart.curvilinearError();
00359     g4error = TrackPropagation::algebraicSymMatrix55ToG4ErrorTrajErr( initErr , charge); //The error matrix
00360   }
00361   LogDebug("Geant4e") << "G4e -  Error matrix: " << g4error;
00362 
00363   G4ErrorFreeTrajState* g4eTrajState = 
00364     new G4ErrorFreeTrajState(particleName, g4InitPos, g4InitMom, g4error);
00365   LogDebug("Geant4e") << "G4e -  Traj. State: " << (*g4eTrajState);
00366 
00367   //Set the mode of propagation according to the propagation direction
00368   G4ErrorMode mode = G4ErrorMode_PropForwards;
00369 
00370   if (propagationDirection() == oppositeToMomentum) {
00371     mode = G4ErrorMode_PropBackwards;
00372     LogDebug("Geant4e") << "G4e -  Propagator mode is \'backwards\'";
00373   } else if(propagationDirection() == alongMomentum) {
00374     LogDebug("Geant4e") << "G4e -  Propagator mode is \'forwards\'";
00375   } else {
00376     //------------------------------------
00377     //For cylinder assume outside is backwards, inside is along
00378     //General use for particles from collisions
00379     LocalVector lmom = cDest.toLocal(cmsInitMom);
00380     LocalPoint lpos = cDest.toLocal(cmsInitPos);
00381     Surface::Side theSide = cDest.side(lpos,0);
00382     if(theSide==SurfaceOrientation::positiveSide){  //outside cylinder
00383       mode = G4ErrorMode_PropBackwards;
00384       LogDebug("Geant4e") << "G4e -  Propagator mode is \'backwards\'";
00385     } else { //inside cylinder
00386       LogDebug("Geant4e") << "G4e -  Propagator mode is \'forwards\'";
00387     }
00388 
00389   }
00390 
00392   // Propagate
00393 
00394   int ierr;
00395   if(mode == G4ErrorMode_PropBackwards) {
00396     //To make geant transport the particle correctly need to give it the opposite momentum
00397     //because geant flips the B field bending and adds energy instead of subtracting it
00398     //but still wants the momentum "backwards"
00399     g4eTrajState->SetMomentum( -g4eTrajState->GetMomentum());
00400     ierr = theG4eManager->Propagate( g4eTrajState, g4eTarget, mode);
00401     g4eTrajState->SetMomentum( -g4eTrajState->GetMomentum());
00402   } else {
00403     ierr = theG4eManager->Propagate( g4eTrajState, g4eTarget, mode);
00404   }
00405   LogDebug("Geant4e") << "G4e -  Return error from propagation: " << ierr;
00406 
00407   if(ierr!=0) {
00408     LogDebug("Geant4e") << "G4e - Error is not 0, returning invalid trajectory";
00409     return TrajectoryStateOnSurface();
00410   }
00411 
00412   // Retrieve the state in the end from Geant4e, converte them to CMS vectors
00413   // and points, and build global trajectory parameters
00414   // CMS uses cm and GeV while Geant4 uses mm and MeV
00415   HepGeom::Point3D<double>  posEnd = g4eTrajState->GetPosition();
00416   HepGeom::Vector3D<double>  momEnd = g4eTrajState->GetMomentum();
00417 
00418   GlobalPoint  posEndGV = TrackPropagation::hepPoint3DToGlobalPoint(posEnd);
00419   GlobalVector momEndGV = TrackPropagation::hep3VectorToGlobalVector(momEnd)/GeV;
00420 
00421 
00422   //DEBUG
00423   LogDebug("Geant4e") << "G4e -  Final CMS point position:" << posEndGV 
00424                       << "cm\n"
00425                       << "G4e -            (Ro, eta, phi): (" 
00426                       << posEndGV.perp() << " cm, " 
00427                       << posEndGV.eta() << ", " 
00428                       << posEndGV.phi().degrees() << " deg)\n"
00429                       << "G4e -  Final G4  point position: " << posEnd 
00430                       << " mm,\tRo =" << posEnd.perp()  << " mm";
00431   LogDebug("Geant4e") << "G4e -  Final CMS momentum      :" << momEndGV
00432                       << "GeV\n"
00433                       << "G4e -  Final G4  momentum      : " << momEnd 
00434                       << " MeV";
00435 
00436   GlobalTrajectoryParameters tParsDest(posEndGV, momEndGV, charge, theField);
00437 
00438 
00439   // Get the error covariance matrix from Geant4e. It comes in curvilinear
00440   // coordinates so use the appropiate CMS class  
00441   G4ErrorTrajErr g4errorEnd = g4eTrajState->GetError();
00442   CurvilinearTrajectoryError 
00443     curvError(TrackPropagation::g4ErrorTrajErrToAlgebraicSymMatrix55(g4errorEnd, charge));
00444   LogDebug("Geant4e") << "G4e -  Error matrix after propagation: " << g4errorEnd;
00445 
00447   // We set the SurfaceSide to atCenterOfSurface.                       //
00449 
00450   SurfaceSideDefinition::SurfaceSide side = SurfaceSideDefinition::atCenterOfSurface;
00451 
00452   return TrajectoryStateOnSurface(tParsDest, curvError, cDest, side);
00453 }
00454 
00455 
00456 //Require method with input TrajectoryStateOnSurface to be used in track fitting
00457 //Don't need extra info about starting surface; use regular propagation method
00458 TrajectoryStateOnSurface
00459 Geant4ePropagator::propagate (const TrajectoryStateOnSurface& tsos, const Cylinder& cyl) const {
00460   const FreeTrajectoryState ftsStart = *tsos.freeState();
00461   return propagate(ftsStart,cyl);
00462 }
00463 
00464 
00465 //
00467 //
00468 
00475 std::pair< TrajectoryStateOnSurface, double> 
00476 Geant4ePropagator::propagateWithPath (const FreeTrajectoryState& ftsStart, 
00477                                       const Plane& pDest) const {
00478 
00479   theSteppingAction->reset();
00480 
00481   //Finally build the pair<...> that needs to be returned where the second
00482   //parameter is the exact path length. Currently calculated with a stepping
00483   //action that adds up the length of every step
00484   return TsosPP(propagate(ftsStart,pDest), theSteppingAction->trackLength());
00485 }
00486 
00487 std::pair< TrajectoryStateOnSurface, double> 
00488 Geant4ePropagator::propagateWithPath (const FreeTrajectoryState& ftsStart,
00489                                       const Cylinder& cDest) const {
00490   theSteppingAction->reset();
00491 
00492   //Finally build the pair<...> that needs to be returned where the second
00493   //parameter is the exact path length. Currently calculated with a stepping
00494   //action that adds up the length of every step
00495   return TsosPP(propagate(ftsStart,cDest), theSteppingAction->trackLength());
00496 }
00497 
00498 std::pair< TrajectoryStateOnSurface, double> 
00499 Geant4ePropagator::propagateWithPath (const TrajectoryStateOnSurface& tsosStart, 
00500                                       const Plane& pDest) const {
00501 
00502   theSteppingAction->reset();
00503 
00504   //Finally build the pair<...> that needs to be returned where the second
00505   //parameter is the exact path length. Currently calculated with a stepping
00506   //action that adds up the length of every step
00507   return TsosPP(propagate(tsosStart,pDest), theSteppingAction->trackLength());
00508 }
00509 
00510 std::pair< TrajectoryStateOnSurface, double> 
00511 Geant4ePropagator::propagateWithPath (const TrajectoryStateOnSurface& tsosStart,
00512                                       const Cylinder& cDest) const {
00513   theSteppingAction->reset();
00514 
00515   //Finally build the pair<...> that needs to be returned where the second
00516   //parameter is the exact path length. Currently calculated with a stepping
00517   //action that adds up the length of every step
00518   return TsosPP(propagate(tsosStart,cDest), theSteppingAction->trackLength());
00519 }